Error using Moq's Verify method - c#

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.

Related

Moq and testing for a specific call to a service with no other calls

Say I have a reference to a service called myService. It has a method called MyMethod which takes an int parameter.
Using Moq, I want to test a particular scenario that means MyMethod is called once with a specific value (let's say it's 3) and to also ensure that no other call is made.
If I wrote:
myService.Verify(o => o.MyMethod(It.IsAny<int>()), Times.Once);
Then this would ensure the method was only called once but I do not know if it was called with 3.
If I wrote:
myService.Verify(o => o.MyMethod(3), Times.Once);
Then this would ensure the method was only called once with 3 but I do not know if it was called any other times with values other than 3.
So, if I want to ensure both that it was only called once with a 3 and it was not called any other times then I would need to have two Verify calls like this:
myService.Verify(o => o.MyMethod(3), Times.Once);
myService.Verify(o => o.MyMethod(It.IsAny<int>()), Times.Once);
Is there any Moq convention that allows me to achieve the same thing with just one Verify call?

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();

Overloaded return values in MOQ

I'm working on understanding a bit more about Setup and unit testing with Moq. I've run into a slight problem though.
What I want to do is something like this:
view.Setup(x => x.GetReference("object1")).Returns(object1);
view.Setup(x => x.GetReference("object2")).Returns(null);
However, when I make my call this way, I never hit the block of code that would react to the Null statement. How am I supposed to set up my Setups so that they will behave in a specific way when they are called by a specific argument?
The moq overloads two ways to return a value:
instance: Returns(instance);
delegate(Func<T>): Returns(()=>new Foo());
I think that the problem is caused from the ambiguousness for which Returns method is to be used.
So, you need to pass in the explicit type of NULL for the second setup of your code as the following ways:
view.Setup(x => x.GetReference("object2")).Returns((ExplicitType)null);
view.Setup(x => x.GetReference("object2")).Returns(() => null);

Moq Error: Cannot cast 'AnObject' to 'System.Delegate'

I have been trying to get past this problem for a couple of days now to no avail. I am trying to test the functionality of AnObject.AnAction (preemptive apologies, I have to obfuscate class/method names.) My goal is to keep MyTestObj.do_work(AnObject) from actually doing anything when it is called. It has code that I do want to be called in a unit test environment.
Here is my Unit test code:
Mock< MyTestObj > myTestObj_mock = new Mock< MyTestObj > ();
myTestObj_mock.Setup( e => e.do_work( It.IsAny< AnObject > () ) );
...
AnObject tester = new AnObject();
tester.anAction( myTestObj_mock.Object );
within the method AnObject.AnAction( MyTestObj mto ):
...
mto.do_work( this );
...
It is at this point when ran that I get this error:
System.InvalidCastException : Unable to cast object of type
'myNamespace.AnObject' to type 'System.Delegate'.
MyTestObj.do_work is a virtual method.
I have absolutely no idea why this error is coming up. I've stepped through the code as NUnit ran it and I am certain that is the point in which it crashes. It will not go any further into the code.
I'm really stumped. Does anybody have any idea what is going on?
Thanks in advance!
***Updates***
I tried to create an instance of AnObject within AnObject.AnAction and pass it instead of 'this':
...
AnObject test = new AnObject();
mto.do_work( test );
...
This did not have any effect.
As your question is written you do not need to setup the myTestObj_mock.do_work().
Setup is used to say, when method X is called return value Y. Or alternativly that when method X is called, exception Z is returned. Ask yourself is that really what I need to do?
Here you aren't returning anything from the method:
mto.do_work( this );
Also, here:
myTestObj_mock.Setup( e => e.do_work( It.IsAny< AnObject > () ) );
You aren't defining any Return for your setup.
You should be able to supply a mock myTestObj_mock without defining the setup in this case. Just remove the line with the Setup and run the test again.
A guess:
If you defined the Setup because you wanted your test to make sure AnObject.AnAction really calls the do_work method, what you need to do is define a Verify method rather than a Setup, likewise:
mock.Verify(foo => foo.Execute("ping"));
or in your case something like
myTestObj_mock.Verify(m => m.do_work(It.IsAny< AnObject > ()), Times.AtLeastOnce());
Another guess:
If you defined the mock because you pass a "this" reference and expect do_work to modify some parameters of "this" for the test to pass then you shouldn't be mocking here. Remember that mocks aren't really instances of your objects, so the code that modify the this reference will never get called.
I was finally able to get to a compiler and play with the code and here is what I found. It is basically what Giles said above for his first part of the question.
Here is the code hint for Setup:
Specifies a setup on the mocked type for a call to a value returning method.
And, here is the actual code for Setup
public ISetup<T> Setup(Expression<Action<T>> expression)
So, Setup is actually setting up the code as an Action (a delegate, basically). When the test runner is run, it hits this point and usually expects to feed the delegate to the Returns method
public IReturnsResult<TMock> Returns(TResult value)
So, this is never done, and instead of Mock running through the whole expected path and negotiating all of the code out, then it returns mistyped values.
Sooo, this is basically where Giles explanation is correct. If you are testing that the do_work method is being called, then you want to use Verify (which truly uses your fake object as a mock). However, if not, then you have no need to even set this up as it does nothing. If that is the case, then maybe that piece of code should not be in that specific code block, but you would be best to evaluate that.
And, finally, the Setup method should only be used if you are truly using your object as a stub, simply using it to inject logic into your code.
Hopefully, that makes sense and helps you with your problem.
Also, a Callback might be of use here depending on what you are doing. But, I am not sure. They have many examples in the Moq quickstart
UPDATE FOR MY ATTEMPT AT RECREATING using Version 4.0.10827...and had no issues
[Test]
public void teststuff()
{
Mock<MyTestObj> myTestObj_mock = new Mock<MyTestObj>();
myTestObj_mock.Setup(e => e.do_work(It.IsAny<AnObject>()));
AnObject tester = new AnObject();
tester.anAction(myTestObj_mock.Object);
}
...
public class MyTestObj
{
public virtual void do_work(AnObject o)
{
}
}
public class AnObject
{
public void anAction(MyTestObj obj)
{
obj.do_work(new AnObject());
}
}

Rhino Mocks - Set a property if a method is called

Is there a way with Rhino Mocks to set a property of a Stub if a method is called.
Something like this: (Fake Code in bold)
callMonitor.Expect(x=>x.HangUp()).SetProperty(callMonitor.InACall = false);
The HangUp method returns void and I can't really change that. But I want my stub to know that the call was hung up when HangUp is called.
You can use the "WhenCalled" method to run your own code when a stub is called; pretty sure it should work with Mocks, too. According to the documentation, WhenCalled is a replacement/upgrade for Callback.
callMonitor.Expect(x => x.HangUp())
.WhenCalled(invocation => callMonitor.InCall = false);
Some info at the end of this post:
http://grahamnash.blogspot.com/2008/10/rhino-mocks-35.html
Yes, you can use the Callback method:
callMonitor.Expect(x => x.HangUp()).Callback(() => callMonitor.InCall = false);
There might be some conditions under which you would need to do this, but generally I would expect that you would simply instrument your mock/stub so that it returns the proper values in response to your code. The only exceptions to this that I can think of are partial mocks where you are testing one part of a class and want to mock the other parts.
Setting a mock on a property is pretty easy.
callMonitor.Expect( x => x.HangUp() );
callMonitor.Expect( x => x.InACall ).Return( false );
If callMonitor is a stub, then you can set the property directly.
callMonitor.Stub( x => x.HangUp() );
callMonitor.InACall = false;
I'm no RhinoMocks expert, but I believe this should work.
SetupResult.For(callMonitor.InACall).Return(false);

Categories

Resources