SetupGet with multiple callbacks - c#

Please see the code below:
mockBusinessLayer.Setup(m => m.Calculate(It.IsAny<integer>(), It.IsAny<integer>())).Callback
(() => mockBusinessLayer.SetupGet(y => y.FirstNumber).Returns(Helper.FirstNumber));
mockBusinessLayer.Setup(m => m.Calculate(It.IsAny<integer>(), It.IsAny<integer>())).Callback
(() => mockBusinessLayer.SetupGet(y => y.SecondNumber).Returns(Helper.SecondNumber));
Calculate() accepts two integers and adds them together. How do I setup multiple SetupGets on the same mock object? The above code only sets up the Get callback on SecondNumber (because it is the last time SetupGet is called).
Update
This is the function I am trying to test:
public CalculatorDTO Calculate(int NumberOne, int NumberTwo)
{
_Calculator.Calculate(NumberOne, NumberTwo);
return Mapper.Map<CalculatorDTO>(_changeCalculator);
}
}
Is it better to do this:
mockBusinessLayer.Setup(x => x.FirstNumber).Returns(Helper.FirstNumber);
mockBusinessLayer.Setup(x => x.SecondNumber).Returns(Helper.SecondNumber);

You say:
The above code only sets up the Get callback on SecondNumber (because it is the last time SetupGet is called).
But that's not quite right: your calls to Setup of Calculate are identical and thus the second one overrides the first. It's as if the first Setup never occurred.
Putting the calls to SetupGet in the Callback is unnecessary and confusing. I'd set it up like this:
mockBusinessLayer.SetupGet(y => y.FirstNumber).Returns(Helper.FirstNumber)
mockBusinessLayer.SetupGet(y => y.SecondNumber).Returns(Helper.SecondNumber)
mockBusinessLayer.Setup(m => m.Calculate(It.IsAny<integer>(), It.IsAny<integer>()));
Any time FirstNumber is gotten, it will return Helper.FirstNumber, and likewise for SecondNumber returning Helper.SecondNumber.
All that being said, without more of your code (What type is _Calculator? Does your mockBusinessLayer really expose FirstNumber/SecondNumber and Calculate?) it's hard to offer more complete steps to move forward. For instance, you don't show the setup of your Mapper.Map method, which you'll need if you want to test this method.
In response to your update...
SetupGet offers a slightly cleaner API: you're required to pass a Func, while Setup will allow you to pass an Action; it returns a slightly more restricted ISetupGet interface. SetupGet also has better semantics, indicating to readers that you intend to set up only the get.
In the Moq source they actually boil down to the same code so either get the job done just as well.

Related

FakeItEasy assert that method call to method

I have an unit-test written with FakeItEasy v2.2.0.
The test tests that a method, let call it MethodA call to MethodB.
The simple class:
public class Foo
{
public virtual void MethodA()
{
MethodB();
}
public virtual void MethodB() { }
}
The simple test:
var foo_fake = A.Fake<Foo>(options => options.CallsBaseMethods());
foo_fake.MethodA();
A.CallTo(() => foo_fake.MethodA()).MustHaveHappened()
.Then(A.CallTo(() => foo_fake.MethodB()).MustHaveHappened());
With FakeItEasy 2.2.0, the code passed.
But when we upgrade to 5.1.0, the code throw exception that says:
The calls were found but not in the correct order among the calls
When we say the method is called? At the start of execution, or at the end?
Or, what is the right way to test this case?
Update: this was a bug, and has been fixed. As of FakeItEasy 5.1.1, the behaviour is restored to what it was in 2.2.0
We record that a call was made after the call is finished, so in your case, the order would be
execute methodA
execute methodB
record that methodB happened
record that methodA happened
However, in 3.4.2, we released the fix to Setting ref argument values masks incoming argument values used to verify calls. This moved the point at which we record the call's "sequence number" from within the CastleInvocationCallAdapter to the FakeManager. The former would have recorded methodA's invocation before the call to methodB.
It's a shame this breaks your use case. I consider the new behaviour to be a bug, and created issue #1583 - Calls are recorded after applying the best rule, not when received on GitHub.
Personally, though, I'd look at the test (which I assume is more complicated than you presented here). I'd take #Nikosi's advice and not check the order of the calls. Knowing that they were both called (or even just that methodB was called) might be enough.
The call to MethodB happens and completes before MethodA has completed. Which explains the order message. It (FakeItEasy) records called at the end of the invocation of the member.
To prove my point, the following passes when tested
A.CallTo(() => foo_fake.MethodB()).MustHaveHappened() //<-- Note MethodB checked first
.Then(A.CallTo(() => foo_fake.MethodA()).MustHaveHappened());
I suggest the following
//Arrange
var foo_fake = A.Fake<Foo>(options => options.CallsBaseMethods());
Action<Foo> subject = foo => foo.MethodA();
//Act
subject(foo_fake);
//Assert
A.CallTo(() => foo_fake.MethodA()).MustHaveHappened();
A.CallTo(() => foo_fake.MethodB()).MustHaveHappened();

How does NSubstitute .Returns<T>() work?

How does the .Returns<T> (this T value, ... ) extension method work under the hood?
Specifically, how does .Returns know what method it is intended to configure just from the result of executing that method?
Example:
public interface ICalculator { Add(int a, int b); }
// create mock
var calculator = Substitute.For<ICalculator>();
// How does this piece work under the hood?
calculator.Add(1, 2).Returns(3);
Whenever a substitute receives a call, it records information about the call, and updates some global state (threadlocal, as Scott pointed out) recording that it was the most recent substitute called.
When .Returns runs, it looks up the last substitute called, then tells the substitute that its last call should be stubbed to return that specific value. (It also removes it from the collection of received calls, so if we run .Received() the stubbed call doesn't get confused for a real one.)
calculator
.Add(1, 2) // substitute records Add(1,2) called. Last substitute
// set to `calculator`. Returns default `int` in this case.
.Returns(3) // Looks up last sub, sets its last call to return 3.
I think this is a reasonable approximation of what happens. To add a little more precision in case you want to look at the code, a substitute is a dynamic proxy which forwards every call to a "call router" which handles all the logic of the substitute (storing calls, configuring calls, adding callbacks etc.). The global state is a SubstitutionContext, which stores the last call router that received a call.
(Repo links are to v4.0.0-rc1 tag. Later versions may change, but the overall idea should remain fairly consistent.)
I believe that it works by saving a context (called ISubstitutionContext) in thread local storage when a mocked method is called. Then the call to Returns grabs this context and sets appropriate data in the return object.
The actual implementation of the mocked method would (extremely crudely) look something like:
//Dynamically created mock
public int Add(int a, int b)
{
var context = new SubstitutionContext("Add", ...);
//CallContext.LogicalSetData or
//ThreadStatic or
//ThreadLocal<T> or
//...
return 0;
}
//In some extension class
public static ConfiguredCall Returns<T>(this T value, ...)
{
var context = SubstitutionContext.Current; //Gets from thread local storage
return context.LastCallShouldReturn(value);
}

How do I use MoqSequence

I want to test the order of execution of the methods of three dependencies within a class. That is, check to ensure a method is called on class a, then b and then c and are executed and in that order.
I was going to use the Moq.Sequence library but I have found that sequence testing is now supported out of the box. The only thing is that documentation is very light on the ground about the MoqSequence class, and I cant find a concrete example.
Also, my question is not about whether this is right or wrong specifically, but I believe testing the order of execution is a valid test (bit of a grey area here?)
There is bug when using MockSequence on same mock. It definitely will be fixed in later releases of Moq library (you can also fix it manually by changing Moq.MethodCall.Matches implementation).
If you want to use Moq only, then you can verify method call order via callbacks:
int callOrder = 0;
writerMock.Setup(x => x.Write(expectedType)).Callback(() => Assert.That(callOrder++, Is.EqualTo(0)));
writerMock.Setup(x => x.Write(expectedId)).Callback(() => Assert.That(callOrder++, Is.EqualTo(1)));
writerMock.Setup(x => x.Write(expectedSender)).Callback(() => Assert.That(callOrder++, Is.EqualTo(2)));

Error using Moq's Verify method

I am experiencing an issue with Moq in my unit testing and I am not sure where I am going wrong.
I have a method in my interface with like this:
void WriteToRegistryKey (String key, Object value);
and I am unit testing it like this:
var testRegistry = new Mock<IRegistry>();
testRegistry.Setup(x => x.WriteToRegistryKey(It.IsAny<string>(), It.IsAny<int>()));
Utility testUtility = new ConfigUtil(testRegistry.Object);
testUtility.UpdateRegistry();
testRegistry.Verify(x => x.WriteToRegistryKey("MaxNumLogFiles", 10));
Under the hood when I call testUtility.UpdateRegistry() it calls my WriteToRegistryKey I want to test that WriteToRegistryKey
method passing in the correct values.
However I receive this when I run the test:
Moq.MockException :
Expected invocation on the mock at least once, but was never performed: x => x.WriteToRegistryKey("MaxNumLogFiles", (Object)10)
Configured setups:
x => x.WriteToRegistryKey(It.IsAny<String>(), It.IsAny<Int32>()), Times.Never
Performed invocations:
IRegistry.WriteToRegistryKey("MaxNumLogFiles", 10)
If I change my testRegistry.Verify to:
testRegistry.Verify(x => x.WriteToRegistryKey("MaxNumLogFiles", It.IsAny<object>()));
it works, so the issue seems to be around the second parameter the WriteToRegistryKey method takes, and the difference between int and object, but I cant seem
to figure it out.
Thanks for all help!
It would be helpful to see the body of implementation of testUtility.UpdateRegistry(); how the .WriteToRegistryKey method is called there.
However:
I would remove the line where you setup the testRegistry mock:
testRegistry.Setup(x => x.WriteToRegistryKey(It.IsAny<string>(), It.IsAny<int>()));
Because, you want to test it, if it was called with correct arguments or not. There is no reason to setup that with Moq.
and if your test passes with
testRegistry.Verify(x => x.WriteToRegistryKey("MaxNumLogFiles", It.IsAny<object>()));
It could mean two things:
Your WriteToRegistryKey method is called with other then 10 value - error in UpdateRegistry method
or it's null, because you setup it with:
It.IsAny<string>(), It.IsAny<int>()
When you use It.IsAny<type>() it could be also null.

RhinoMocks - Fetching parameters of called functions

Using RhinoMocks - can I fetch the parameters of a called function? I mean; can I get some of the unknown parameters from the function call out?
I have a mock, and I expect some function to be called on this. I know one of the parameters, but the other one is unknown as this comes from the class that uses the mock and calls a function on it. More specificly - in this case - the unknown argument is a lambda function. This is a callback function that is supposed to be called when the function is finished executing. As the mock prevents the callback from being called I want to fetch it and call it myself.
So; I want to check that the function was called. I want to make sure some of the arguments were the expected ones. And I want to get out the unknown arguments to do some operations on them afterwards.
Assuming both arguments are ints (for simplicity) I'd like to do something like this:
int unknownInt;
_fakeSomething.AssertWasCalled(factory => factory.Foo(1, out unknownInt));
// then play around with unknownInt..
Can this be done? I see there is an Arg.Out, but couldn't quite make it work..
Note: Updated the question as it seemed to be misleading.
Arg<string>.Matches(arg => you got the argument here...);
UPDATE:
To fetch the second argument made on the first call of the Foo method on _fakeSomething:
string someArg = null;
var args = _fakeSomething.GetArgumentsForCallsMadeOn(
x => x.Foo(0, 0),
x => x.IgnoreArguments()
);
var int = (int)args[0][1];
Not sure if it can be done, but testing like that can result in unreliable tests, as you don't know the actual paramter that was passed in.
If possible, test on explicit data. If you f.eks pass in null instead of a real value your test will likely pass for the wrong reason.
Testing with Arg.Is.Anything should be done carefully and when you truly don't care about the parameter, such as in AssertWasNotCalled.

Categories

Resources