Overloaded return values in MOQ - c#

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

Related

Rhino Mocks - MethodInvocation.ReturnValue vs IMethodOptions.Return

Playing around with Rhino Mocks, i just stumbled upon a strange behaviour, which I cannot understand.
Setting up my Stub the following way works as expected - 42 is returned
var generator = MockRepository.GenerateStub<INumberGenerator>();
generator.Stub(x => x.GetNumber()).Return(42);
Then I tried using the WhenCalled(Action<MethodInvocation> action) extension, which I used so far only for void functions:
generator.Stub(x => x.GetNumber()).WhenCalled(mi => mi.ReturnValue = 42);
This code throws me an exception Method 'INumberGenerator.GetNumber();' requires a return value or an exception to throw.. Ok, I've added .Return(55) - and now things start to get weird:
generator.Stub(x => x.GetNumber()).WhenCalled(mi => mi.ReturnValue = 42).Return(55);
Which now returns 42, instead of 55. Note that the MethodInvocation.ReturnValue only works when adding the .Return(..) statement which then has absolutely no effect on the returnvalue - which confuses me a lot. Can anybody explain this behaviour?
Rhino Mocks requires you to specify a Return() call at the end of an Expect() chain (in your case, when you're setting expectation for your stub), so that it can determine the type of the return result.
So, in effect, the return value in WhenCalled() is only used. Any value in Returns() would do (and not be used) as long as it is of the same type.
Not explicitly mentioned in the documentation I think.

Moq returns the same result for different IEnumerable parameter setups

I have come across a very strange behavior in moq and I cannot understand whether it's a bug or I am doing something wrong. Here is the example:
List<CustomerDataTransaction> transactions0 = GetTransactionsSomehow();
List<CustomerDataTransaction> transactions1 = GetTransactionsSomehow();
var portfolioTransactions0 = new List<IPortfolioTransaction>();
var portfolioTransactions1 = new List<IPortfolioTransaction>();
m_TransactionMapperMock
.Setup(m => m.CreatePortfolioTransactions(transactions0))
.Returns(portfolioTransactions0);
m_TransactionMapperMock
.Setup(m => m.CreatePortfolioTransactions(transactions1))
.Returns(portfolioTransactions1);
I have checked that transaction0 is not equal to transactions1, so it's for sure different lists. But the mock returns portfolioTransactions1 twice when called with different parameters (transactions0 and transactions1). I tried to figure out what was wrong, but I did not find any reasons. Then I have added dummy elements to each of the lists and that has fixed it, mock started to return different values as planned. Is this a bug of Mock or I don't get something? As far as I understand the values inside the list should not affect it at all.
P.S. I don't know if it's important or not but the method accepts IEnumerable<CustomerDataTransaction>
Consider trying:
It.Is<IEnumerable<CustomerDataTransaction>>(t => t == transactions1))
From memory I thought Moq used reference equality
Expanding on NinjaNye's answer, using It.Is satisfies the test is because it ensures that you are looking at the exact instance of the object, not the equality operator.
With your testing framework, if you say Assert.NotEqual and give it two objects, it uses the equality operator and says one empty list equal to the other. Think about being able to compare objectA.Property1 to objectA.Property2. It makes sense that Assert.Equal would look at the values, not the instance of the value.
Xunit provides a method Assert.Same, which will provide the same functionality as Moq's It.Is<>, verifying it is the same instance of the object. I believe that most of the popular testing frameworks today provide similar behavior.

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.

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

How to verify that method was NOT called in Moq?

How do I verify that method was NOT called in Moq?
Does it have something like AssertWasNotCalled?
UPDATE: Starting from Version 3.0, a new syntax can be used:
mock.Verify(foo => foo.Execute("ping"), Times.Never());
Run a verify after the test with the Times.Never() option.
_mock.Object.DoSomething()
_mock.Verify(service => service.ShouldntBeCalled(), Times.Never());
UPDATE: Since version 3, check the update to the question above or Dann's answer below.
Either, make your mock strict so it will fail if you call a method for which you don't have an expect
new Mock<IMoq>(MockBehavior.Strict)
Or, if you want your mock to be loose, use the .Throws( Exception )
var m = new Mock<IMoq>(MockBehavior.Loose);
m.Expect(a => a.moo()).Throws(new Exception("Shouldn't be called."));
Stolen from: John Foster's answer to the question, "Need help to understand Moq better"
One of the things that you might want to test is that the pay method
does not get called when a person aged over 65 is passed into the
method
[Test]
public void Someone_over_65_does_not_pay_a_pension_contribution() {
var mockPensionService = new Mock<IPensionService>();
var person = new Person("test", 66);
var calc = new PensionCalculator(mockPensionService.Object);
calc.PayPensionContribution(person);
mockPensionService.Verify(ps => ps.Pay(It.IsAny<decimal>()), Times.Never);
}
This does not work in recent versions of Moq (since at least 3.1), it should be specified in the Verify method as mentioned in the
answer.
Actually, it's better to specify .AtMost(0) after the Returns statement.
var m = new Mock<ISomething>();
m.Expect(x => x.Forbidden()).Returns("foo").AtMost(0);
Although the "throws" also works, AtMost(0) is more expressive IMHO.
Using VerifyNoOtherCalls (requires Moq 4.8 or later)
This answer is an indirect approach. Instead of checking that a particular method wasn't called, you check that no unexpected calls were made in general.
Consider that a thorough test of a mock does 2 things:
Verify that all expected calls were made
Verify that no unexpected calls were made
If you're already doing step 1, adding step 2 is trivial:
// Step 1 (if relevant - see note below)
mock.Verify(..., Times.Exactly(2));
mock.Verify(..., Times.Once());
// ...
// Step 2
mock.VerifyNoOtherCalls();
Notes
If you omit step 1, step 2 will simply ensure no calls were made to the mock at all.
This does not require a strict mock.
Source: Moq Quickstart
I realise this is a very old question, but it just appeared in my sidebar, and I'd like to add my solution.
Many unit tests appear to mock several functions, as part of the setup, but then aren't used during the test.
Surely it's better to enable strict mocking (which means anything not explicitly setup will throw an exception), and then don't set up any functions you don't expect to be called. Or to put it another way, only set up the functions that one test expects to be called, and anything else will thrown an exception.
var thingBeingTested = new Mock<IThink>(MockBehaviour.Strict);
thingBeingTested.ThisWillThrowAnExceptionBecauseItHasNotBeenMocked();
Suppose you have this method and you want to test that it's not being called
//Setup
var databaseSessionMock = new Mock<IDatabaseSession>();
databaseSessionMock.Setup(m => m.Commit()).Returns(true).Verifiable();
RepositoryFactory.Configure<IDatabaseSession>(databaseSessionMock.Object);
you can test like this
databaseSessionMock.Verify(m => m.Commit(It.IsAny()), Times.Never(), "Database Session mock object was not used");
Use .AtMostOnce();
After the real test, call the method again. If it throws an exception, it was called.

Categories

Resources