Why am I getting 'Call to unconfigured method' when using wrapped functionality? - fakeiteasy

Using version 7.3.0 of FakeItEasy.
In following code I am getting message that call to method GetById is not configured, yet I am configuring it. What I am doing wrong?
There is no overload for the GetById method.
var fakeConnection = A.Fake<IEventStoreConnection>();
var fakeResolver = A.Fake<IEventResolver>();
var logger = A.Fake<ILogger<DummyAggregateRepository>>();
var repository = new DummyAggregateRepository(fakeConnection, fakeResolver, logger);
var fakeRepository = A.Fake<DummyAggregateRepository>(
o =>
{
o.Wrapping(repository);
o.Strict();
});
var aggregateId = Guid.NewGuid();
A.CallTo(() => fakeRepository.GetById(aggregateId, A<CancellationToken>._))
.CallsWrappedMethod();
var fixture = new AutoFixture.Fixture();
var events1 = fixture.CreateMany<DummyAggregate.EventOne>(10).Cast<Event>();
var events2 = fixture.CreateMany<DummyAggregate.EventTwo>(10).Cast<Event>();
var events = events1.Union(events2).ToList();
A.CallTo(
() => fakeRepository.GetEvents(
"dummyAggregate-" + aggregateId.ToString("N"),
aggregateId.ToString(),
A<CancellationToken>._))
.Returns(events);
var aggregate = await fakeRepository.GetById(aggregateId, default);
GetById implementation is virtual method
public virtual async Task<TAggregate> GetById(Guid aggregateId, CancellationToken ct)
{
ct.ThrowIfCancellationRequested();
var streamName = this.GetStreamName(aggregateId);
using var scope = EventStoreCommon.CreateScope(Tracer.Instance, nameof(this.GetById), streamName);
var events = await this.GetEvents(streamName, aggregateId.ToString(), ct);
if (events.Any() == false)
{
throw new AggregateNotFoundException(aggregateId, typeof(TAggregate));
}
var aggregate = new TAggregate();
foreach (var #event in events)
{
aggregate.ApplyEvent(#event);
}
return aggregate;
}
Error reported
FakeItEasy.ExpectationException: Call to unconfigured method of strict fake: MyCompany.EventStore.Test.AggregateRepositoryTests.DummyAggregateRepository...
FakeItEasy.ExpectationException
Call to unconfigured method of strict fake: MyCompany.EventStore.Test.AggregateRepositoryTests.DummyAggregateRepository.GetById(aggregateId: d8d0445d-7f82-4636-82fc-2e8f14be7f3d, ct: System.Threading.CancellationToken).
at FakeItEasy.Core.StrictFakeRule.Apply(IInterceptedFakeObjectCall fakeObjectCall) in C:\projects\fakeiteasy\src\FakeItEasy\Core\StrictFakeRule.cs:line 53
at FakeItEasy.Core.FakeManager.ApplyBestRule(IInterceptedFakeObjectCall fakeObjectCall) in C:\projects\fakeiteasy\src\FakeItEasy\Core\FakeManager.cs:line 276
at FakeItEasy.Core.FakeManager.FakeItEasy.Core.IFakeCallProcessor.Process(InterceptedFakeObjectCall fakeObjectCall) in C:\projects\fakeiteasy\src\FakeItEasy\Core\FakeManager.cs:line 178
at FakeItEasy.Creation.CastleDynamicProxy.CastleDynamicProxyGenerator.ProxyInterceptor.Intercept(IInvocation invocation) in C:\projects\fakeiteasy\src\FakeItEasy\Creation\CastleDynamicProxy\CastleDynamicProxyGenerator.cs:line 187
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Castle.Proxies.DummyAggregateRepositoryProxy.GetById(Guid aggregateId, CancellationToken ct)
at MyCompany.EventStore.Test.AggregateRepositoryTests.GetByIdTests.When_Stream_Exists_Should_Create_Instance_Of_Aggregate_With_Applied_Events() in C:\github\MyCompany_2\libraries\eventstore\test\MyCompany.EventStore.Test\AggregateRepositoryTests\GetByIdTests.cs:line 131
at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__139_0(Object state)
at Xunit.Sdk.AsyncTestSyncContext.<>c__DisplayClass7_0.<Post>b__1(Object _) in C:\Dev\xunit\xunit\src\xunit.execution\Sdk\AsyncTestSyncContext.cs:line 75

Updated after getting new code and stack trace. Original answer left below
I think it's a bug.
Boring explanation:
Strict and Wrapping each add rules to the front of the faked object's rules list. The rules apply to all incoming calls. The first rule found that matches a call is triggered. So in your configuration, Wrapping is added making the Fake attempt to forward all calls to the wrapped object. Then Strict, so now the Fake will reject all calls.
You'd then expect
A.CallTo(() => fakeRepository.GetById(aggregateId, A<CancellationToken>._))
.CallsWrappedMethod();
to add a rule that would cause an incoming matching GetById call to be forwarded to the wrapped method, but the implementation of CallsWrappedMethod
appears to be missing a this.AddRuleIfNeeded() call around line 127. (You can see that CallsBaseMethod just above has this call.)
I've verified that no rule is added by the CallsWrappedMethod configuration. Likely has been broken since implemented in FakeItEasy 6.0.0 (issue #1717).
I created issue #1870 which is now fixed and released as part of FakeItEasy 7.3.1.
Original response, which was wrong, but did ask for more info:
Likely because a call was made to an unconfigured method on a strict faked repository.
We can't see DummyAggregateRepository, so there's going to be some speculation here. Based on the lack of errors earlier, I
assume that GetById is virtual or abstract, so your call should be passed to the wrapped instance.
Nothing jumps out at me as I read your question, but this sort of thing usually pops up when
a call is made to a different fake object than expected, or
a call is made to a different method than expected, usually because there's an overload and the wrong method was configured
a call is made to the expected fake object method, but with unanticipated arguments
If you edit your question, supplying
the FakeItEasy version you're using
the definition of DummyAggregateRepository, and
the entire exception that's returned, including stack traces
we may be able to help better.

Related

Mocking Httpcalls always return NullPointerException

I'm trying to mock Http calls for unit test.
To do that I have done the following, I have created a RequestMock case class:
case class RequestMock() {
def sendRequest(httpRequest: HttpRequest)(implicit actorSystem: ActorSystem): Future[HttpResponse] = {
Http().singleRequest(httpRequest)
}
}
and in my service, I have written the following piece of code :
case class Service(requestHandler: RequestMock) {
....
for {
response <- {
requestHandler.sendRequest(
HttpRequest(
method = HttpMethods.GET,
uri = "http://database:9000"
)
)
} yield {
response
}
}
For the unit test, I'm trying to mock HttpCalls, to do that, I have done the following :
def test_2 = mock[RequestMock]
And for defining the mock behaviour I have done the following
when(test_2.sendRequest(
HttpRequest(
method = HttpMethods.GET,
uri = "http://database:9000")
)).thenReturn{
Future(
HttpResponse(
StatusCodes.OK,
entity = HttpEntity(ContentTypes.`text/plain(UTF-8)`,"connection established"))
But, when I execute unit tests, I always get the following error:
java.lang.NullPointerException
Does anyone know how I can solve this issue ?
A couple of problems.
First of all, test_2 should be a val, not a def.
With def like you have it, you get a different instance every time you access it. So, you define the stub on one instance, but then create your Service with a different one, that does not have sendRequest defined, so returns null by default, and that causes your NPE.
The next problem, that you will probably encounter after you fix this one is that you are not defining all of the behavior.
when(test_2.sendRequest(
HttpRequest(
method = HttpMethods.GET,
uri = "http://database:9000")
))
Only creates a stub for a method call with this specific parameter value. So, if your tests try to make a POST for example or hit a different endpoint, you'll get an NPE again.
Even if you only ever use one request, it is better to define the stub for any argument, to avoid weird NPE failures if the code happens to send a different one (you are writing a test, so should not just assume automatically, that the code will always do what you expect - you would not need the test in the first place if that was the case):
when(test2.sendRequest(any)),thenReturn(Future.successful(...))
(Note Future.successful above – that's the correct way to create Future that is immediately satisfied, what you are doing makes it run on a thread ... not a big deal in your case, but still icky).
Then, after the test code is run, you can check that the parameter value passed to the sendRequest was actually what you expect:
verify(test2)
.sendRequest(HttpRequest(method = HttpMethods.GET, uri = "http://database:9000"))

Dynamics CRM - Unit Testing a plugin with RhinoMocks give weird result

I am writing a unit test for a plugin using Dynamics CRM with RhinoMocks.
After stubbing out the OrganizationService.Retrieve() method, when I invoke the stubbed out method, I am getting null back.
From what I can see (correct me if I'm wrong), is that the stubbed out method signature must the same as the invocation signature.
Here is my code:
TestSetup
var someGuid = Guid.Empty;
var organisationServiceMock = MockRepository.GenerateMock<IOrganizationService>();
organisationServiceMock.Expect(x => x.Retrieve("someCrmEntity", someGuid, SomeCrmEntityColumnSetQuery.ColumnSet))
.Return(new Entity
{
LogicalName = "someCrmEntity",
Id = Guid.NewGuid(),
});
SomeCrmEntityColumnSetQuery Code
public static class SomeCrmEntityColumnSetQuery
{
public static ColumnSet ColumnSet => new ColumnSet("column1", "column2");
}
Invocation Code
var someEntity = organisationServiceMock.Retrieve("someCrmEntity", someGuid, SomeCrmEntityColumnSetQuery.ColumnSet);
//someEntity is null
Things I have tried
Removed the ColumnSet and replaced it with null - this works
Replaced the static class SomeCrmEntityColumnSetQuery with a default instance (new ColumnSet())
I have set the someGuid to Guid.Empty thinking that it was not "joining" on the correct Guid hence the null return value.
I have tried to replace .Expect() with .Stub() - no joy
Edit
In the expectation, I have tried the .WhenCalled(...) and that is how I found out that if I replace the columnSet argument with a null in the expectation and the invocation, it works. So it's go to do with something in my static class that represents a ColumnSet. The code works as I have it running in my DEV environment.
If anyone can share some light on this, that would be magic!
Charles
So I found the answer after watching a PluralSight video on RhinoMocks.
My problem was that when setting up the stub, the stub does not take values but rather the signature of the method that you are stubbing out. For e.g:
var organisationServiceMock = MockRepository.GenerateMock();
//Wrong
organisationServiceMock.Expect(x => x.Retrieve("someCrmEntity", someGuid, SomeCrmEntityColumnSetQuery.ColumnSet)).Return(new Entity());
//The stub does not care about what values are being sent into the method when invoked but rather if the method signature types match.
//Correct
organisationServiceMock.Expect(x => x.Retrieve(Arg.Is.Anything, Arg.Is.Anything, Arg.Is.Anything)).Return(new Entity());
//During the invocation, stubbed method now expects the first argument to be a string, then 2nd to be a Guid, 3rd to be a ColumnSet.
I hope this helps anyone who has also been struggling with this. :)

FakeItEasy expectation fail against HashSet comparisons

I am using Xamarin Studio 5.2 on Mac OS X 10.9.4 with NUnit 2.6.3 and FakeItEasy 1.23.0.
When I run tests for this code:
using System;
using ValueSet = System.Collections.Generic.HashSet<uint>;
using NUnit.Framework;
using FakeItEasy;
namespace SetTest
{
[TestFixture]
class TestFixture
{
[Test]
public void CallsUsersWithSetAndReducedSet()
{
var values = new ValueSet { 1, 2, 3 };
var setUser = A.Fake<SetUser>();
ClassUnderTest testInstance = new ClassUnderTest();
using (var scope = Fake.CreateScope())
{
testInstance.RunWith(setUser);
using (scope.OrderedAssertions())
{
A.CallTo(() => setUser.Use(A<ValueSet>.That.IsEqualTo(values))).MustHaveHappened(Repeated.Exactly.Once);
A.CallTo(() => setUser.Use(A<ValueSet>.That.Matches(set =>
set.Count == 2 && set.Contains(1)))).MustHaveHappened(Repeated.Exactly.Once);
}
}
}
}
public class SetUser
{
public virtual void Use(ValueSet set)
{
}
}
class ClassUnderTest
{
public static void Main(string[] arguments)
{
}
public void RunWith(SetUser setUser)
{
var values = new ValueSet { 1, 2, 3 };
setUser.Use(values);
values.Remove(3);
setUser.Use(values);
}
}
}
I get the following error output:
FakeItEasy.ExpectationException: Assertion failed for the following call: SetTest.SetUser.Use(1[System.UInt32]>) Expected to find it exactly once but found it #0 times among the calls:
1. SetTest.SetUser.Use(set: System.Collection.Generic.HashSet1[System.UInt32]) repeated 2 times
I don't understand what is causing this failure and how to fix it.
What is needed to get this type of test to pass?
#Tim Long is on the right track in his comment.
Here's a little more detail, as well as updates to respond to your comments of 2014-08-11 03:25:56:
The first reason the first MustHaveHappened fails:
According to the FakeItEasy argument constraints documentation, That.IsEqualTo tests for "object equality using object.Equals". That's what's causing the unexpected behaviour.
Not passing values into the method isn't necessarily a problem, or wouldn't be if ValueSet.Equals performed a value comparison, but ValueSet is a HashSet<uint>, so you can see from that class's method documentation that it doesn't—it uses object.Equals, which tests for reference equality. Thus, your IsEqualTo assertion fails. If you use a more sophisticated matcher that performed a value-type comparison for HashSet, perhaps something closer to what you use in your second A.CallTo, or maybe something using That.Contains, I think you'll have better success.
You may think to use That.IsSameSequenceAs, but be careful if doing so: the HashSet doesn't guarantee the order of the elements in the enumeration, so even if the set has the same elements, you may get a failure.
The second reason the first MustHaveHappened fails:
RunWith changes the contents of the values set between calls to setUser.Use. So the same set is used in two calls, first with 3 elements, then when it has only 2 elements. This means that by the time the first MustHaveHappened call is made, the set has only 2 elements, so the comparison fails. You could see this more clearly by writing an argument formatter for the ValueSet. That would provide more information.
The cause of the mismatch is that when a call is made to a faked method, FakeItEasy captures the arguments. However, for reference types, such as ValueSet (HashSet), only the reference to the argument is kept. Thus, if the object is modified later, in particular between the execution and the verification stages of the test, the object will look different than it did at the time of the faked call. See #jimmy_keen's answer to MustHaveHappened fails when called twice on the same object. There's a little more discussion over at FakeItEasy Issue 306 - Verifying multiple method calls with reference parameters.
In this case, the usual approach is to do as he suggests—provide code to capture the important state of the incoming argument at call time, and then query that saved state later.
You might be able to use something like this:
[Test]
public void CallsUsersWithSetAndReducedSet()
{
var capturedValueSets = new List<List<uint>>();
var setUser = A.Fake<SetUser>();
A.CallTo(() => setUser.Use(A<ValueSet>._)) // matches any call to setUser.Use
.Invokes((ValueSet theSet) => capturedValueSets.Add(theSet.ToList()));
ClassUnderTest testInstance = new ClassUnderTest();
testInstance.RunWith(setUser);
Assert.That(capturedValueSets, Has.Count.EqualTo(2),
"not enough calls to setUser.Use");
Assert.That(capturedValueSets[0], Is.EquivalentTo(new uint[] {1, 2, 3}),
"bad set passed to first call to setUser.Use");
Assert.That(capturedValueSets[1], Has.Count.EqualTo(2) & Has.Member(1),
"bad set passed to second call to setUser.Use");
}
You can see that each time Use is called, we add the contents of the ValueSet argument to capturedValueSets. Then at the end we
make sure 2 calls were made, by checking the length of capturedValueSets
make sure that the first time Use was called, the set had the elements 1, 2, and 3. Is.EquivalentTo checks the two lists but ignores order
make sure that the second time Use was called, the set had 2 elements, one of which was 1
By checking the two captured value sets in turn, all the bits about the scopes and ordered assertions became unnecessary.

Handling errors in an observable sequence using Rx

Is there a way to have an observable sequence to resume execution with the next element in the sequence if an error occurs?
From this post it looks like you need to specify a new observable sequence in Catch() to resume execution, but what if you needed to just continue processing with the next element in the sequence instead? Is there a way to achieve this?
UPDATE:
The scenario is as follows:
I have a bunch of elements that I need to process. The processing is made up of a bunch of steps. I have
decomposed the steps into tasks that I would like to compose.
I followed the guidelines for ToObservable() posted here
to convert by tasks to an observables for composition.
so basically I'm doing somethng like so -
foreach(element in collection)
{
var result = from aResult in DoAAsync(element).ToObservable()
from bResult in DoBAsync(aResult).ToObservable()
from cResult in DoCAsync(bResult).ToObservable()
select cResult;
result.subscribe( register on next and error handlers here)
}
or I could something like this:
var result =
from element in collection.ToObservable()
from aResult in DoAAsync(element).ToObservable()
from bResult in DoBAsync(aResult).ToObservable()
from cResult in DoCAsync(bResult).ToObservable()
select cResult;
What is the best way here to continue processing other elements even if let's say the processing of
one of the elements throws an exception. I would like to be able to log the error and move on ideally.
Both James & Richard made some good points, but I don't think they have given you the best method for solving your problem.
James suggested using .Catch(Observable.Never<Unit>()). He was wrong when he said that "will ... allow the stream to continue" because once you hit an exception the stream must end - that is what Richard pointed out when he mentioned the contract between observers and observables.
Also, using Never in this way will cause your observables to never complete.
The short answer is that .Catch(Observable.Empty<Unit>()) is the correct way to change a sequence from one that ends with an error to one that ends with completion.
You've hit on the right idea of using SelectMany to process each value of the source collection so that you can catch each exception, but you're left with a couple of issues.
You're using tasks (TPL) just to turn a function call into an observable. This forces your observable to use task pool threads which means that the SelectMany statement will likely produce values in a non-deterministic order.
Also you hide the actual calls to process your data making refactoring and maintenance harder.
I think you're better off creating an extension method that allows the exceptions to be skipped. Here it is:
public static IObservable<R> SelectAndSkipOnException<T, R>(
this IObservable<T> source, Func<T, R> selector)
{
return
source
.Select(t =>
Observable.Start(() => selector(t)).Catch(Observable.Empty<R>()))
.Merge();
}
With this method you can now simply do this:
var result =
collection.ToObservable()
.SelectAndSkipOnException(t =>
{
var a = DoA(t);
var b = DoB(a);
var c = DoC(b);
return c;
});
This code is much simpler, but it hides the exception(s). If you want to hang on to the exceptions while letting your sequence continue then you need to do some extra funkiness. Adding a couple of overloads to the Materialize extension method works to keep the errors.
public static IObservable<Notification<R>> Materialize<T, R>(
this IObservable<T> source, Func<T, R> selector)
{
return source.Select(t => Notification.CreateOnNext(t)).Materialize(selector);
}
public static IObservable<Notification<R>> Materialize<T, R>(
this IObservable<Notification<T>> source, Func<T, R> selector)
{
Func<Notification<T>, Notification<R>> f = nt =>
{
if (nt.Kind == NotificationKind.OnNext)
{
try
{
return Notification.CreateOnNext<R>(selector(nt.Value));
}
catch (Exception ex)
{
ex.Data["Value"] = nt.Value;
ex.Data["Selector"] = selector;
return Notification.CreateOnError<R>(ex);
}
}
else
{
if (nt.Kind == NotificationKind.OnError)
{
return Notification.CreateOnError<R>(nt.Exception);
}
else
{
return Notification.CreateOnCompleted<R>();
}
}
};
return source.Select(nt => f(nt));
}
These methods allow you to write this:
var result =
collection
.ToObservable()
.Materialize(t =>
{
var a = DoA(t);
var b = DoB(a);
var c = DoC(b);
return c;
})
.Do(nt =>
{
if (nt.Kind == NotificationKind.OnError)
{
/* Process the error in `nt.Exception` */
}
})
.Where(nt => nt.Kind != NotificationKind.OnError)
.Dematerialize();
You can even chain these Materialize methods and use ex.Data["Value"] & ex.Data["Selector"] to get the value and selector function that threw the error out.
I hope this helps.
The contract between IObservable and IObserver is OnNext*(OnCompelted|OnError)? which is upheld by all operators, even if not by the source.
Your only choice is to re-subscribe to the source using Retry, but if the source returns the IObservable instance for every description you won't see any new values.
Could you supply more information on your scenario? Maybe there is another way of looking at it.
Edit: Based on your updated feedback, it sounds like you just need Catch:
var result =
from element in collection.ToObservable()
from aResult in DoAAsync(element).ToObservable().Log().Catch(Observable.Empty<TA>())
from bResult in DoBAsync(aResult).ToObservable().Log().Catch(Observable.Empty<TB>())
from cResult in DoCAsync(bResult).ToObservable().Log().Catch(Observable.Empty<TC>())
select cResult;
This replaces an error with an Empty which would not trigger the next sequence (since it uses SelectMany under the hood.

return statement from within using

using (IDbCommand command = new SqlCommand())
{
IDbDataAdapter adapter = new SqlDataAdapter();
DataSet ds = new DataSet();
adapter.SelectCommand = command;
command.Connection = _dataAccess.Connection;
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "GetProcData";
command.Parameters.Add(new SqlParameter("#ProcID ", procId));
adapter.Fill(ds);
return ds.Tables[0].AsEnumerable();
}
This returns an IEnumerable DataRow The question is that since the return is within the using statement, will it property dispose of the IDBCommand? I know I can easily refactor this so I change the scope of the DataSet outside of the using, but it is more of a wonder than anything else.
Yes, this will work as expected with IDbCommand being properly disposed. The compiler will transform the using block to a try-catch-finally, where Dispose is invoked in the finally block.
Yes, the DB Command will be disposed, so far so good.
You can get troubles with IEnumerables. Because the items could potentially be produced when getting them from the IEnumerable, not when creating the IEnumerable, that is the nature of it. So it depends on how ds.Tables[0].AsEnumerable() is implemented. It could wait with executing the command until you get the first item. This is in the calling code, outside of the using block. You'll get an error, because the command had been disposed.
This is probably not an issue here, but should always be considered when returning IEnumerables (or lambda expressions) from a using block:
using (A a = new A())
{
return someItems.Select(x => a.Get(x));
}
When accessing the first item, a is already disposed and you get an error.
The IDbCommand is disposed correctly. As a rule of thumb when returning from within a using statement you are fine to do so so long as:
The thing you are returning isn't in the clause of the using
statement
The thing being returned isn't a reference created within the block of the using statement.
In the first case the using statement will dispose of the thing you are trying to return and in the second case the variable will go out of scope.
e.g.
//this is fine as result is createsd outside the scope of the block.
bool result = false;
using (SmtpClient mailClient = new SmtpClient())
{
try
{
mailClient.Send(...);
result = true;
}
catch(SmtpException)
{
result = false;
}
finally
{
return result;
}
}
Here, the using(){ ... } statement is our friend. When we exit the block our SmtpClient is disposed, and the result condition will still exist for you to use.
However, say we are writing a WinForm app or WPF app and we wrap a using block around our data context then we create a problem as the context disappears before the control can consume it.
// this will fail when you bind the customers to a form control!
using (DbContext context = new DBContext())
{
context.Customers.Where(c => c.Name.Contains("Bob")).Load();
return context.Customers.Local;
}
Here, the using(){ ... } statement hurts us. As when we come to dataBind our customer to a GridView (or other such databound control) the fact that we have disposed of the DbContext will mean our form has nothing to bind to so it will throw an exception!
HTH
The scope of your IDbCommand object is very clear: between the brackets { and }. As soon as your program flow exits from there, the object is disposed.