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);
Related
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.
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);
I am doing ordered expectations in rhino mocks as described by ayende in this post. My code looks something like this:
using (_mocks.Ordered())
{
Expect.Call(() => _myMock.CallA());
Expect.Call(() => _myMock.CallB(40));
Expect.Call(() => _myMock.CallA());
}
_mocks.ReplayAll();
_myObjectUnderTest.DoStuff();
_mocks.VerifyAll();
After this I would like to add more expectations and test more of my object's methods. I want to do this because I have some basic test methods that do some setup on my test object, and I do not want to have to retest that functionality, so I just call the earlier test method. If I try and add more expectations after VerifyAll() I get an exception: "This action is invalid when the mock object is in verified state."
Part of my problem is that I don't really understand what all of the replay/verify stuff is doing, I just copied code. I am using strict mocks, so any setup code must have matching expectations or it fails. I do not want to duplicate the expectations for my setup code.
Is there a way to reset the mock to be ready to start over in some way?
Short answer: no. Now on to the long answer.
What the replay and verify stuff does is this. Before you call ReplayAll, you are telling Rhino what you expect the methods are going to do. You in a sense are recording calls to the mock objects you've created.
After you've recorded the method calls, you call ReplayAll telling Rhino you're now going to do 'something' that should execute the methods as recorded.
Last, you call VerifyAll asking Rhino to verify whether the methods were actually called as you've recorded them.
Now on to why you really should not want to re-use the mocks. With unit testing/TDD, your unit test should test as little as possible. This is to keep your unit tests simple and transparent. The whole idea of unit testing is that many many many small tests as a whole test the entire system.
For a very good presentation on TDD explaining this and other subjects, see http://www.infoq.com/presentations/integration-tests-scam.
P.S.: One small detail: As long as the methods don't return a result, you can write:
using (_mocks.Ordered())
{
Expect.Call(() => _myMock.CallA());
Expect.Call(() => _myMock.CallB(40));
Expect.Call(() => _myMock.CallA());
}
as:
using (_mocks.Ordered())
{
_myMock.CallA();
_myMock.CallB(40);
_myMock.CallA());
}
(at least with the latest version of Rhino)
Short answer: yes
Longer answer: Try the following
[Test]
public void RhinoMock_PerformMultipleChecks()
{
var myMock = MockRepository.GenerateDynamicMockWithRemoting<IComparable>();
// first round of checks
myMock.Expect(x => x.CompareTo("123")).Return(1);
myMock.Expect(x => x.CompareTo("-12")).Return(-1);
Assert.AreEqual(1, myMock.CompareTo("123"));
Assert.AreEqual(-1, myMock.CompareTo("-12"));
myMock.VerifyAllExpectations();
// reset
myMock.BackToRecord();
myMock.Replay();
// next round of checks
myMock.Expect(x => x.CompareTo(1.23)).Return(1);
myMock.Expect(x => x.CompareTo(-12)).Return(-1);
Assert.AreEqual(1, myMock.CompareTo(1.23));
Assert.AreEqual(-1, myMock.CompareTo(-12));
myMock.VerifyAllExpectations();
// reset
myMock.BackToRecord();
myMock.Replay();
// final round of checks
myMock.Expect(x => x.CompareTo(1.23m)).Return(1);
myMock.Expect(x => x.CompareTo(-12m)).Return(-111);
Assert.AreEqual(1, myMock.CompareTo(1.23m));
Assert.AreEqual(-111, myMock.CompareTo(-12m));
myMock.VerifyAllExpectations();
}
I'm using Moq to create a mock object of HttpResponseBase. I need to be able to test that HttpResponseBase.End() was called in my library. To do this, I specify some text before the call and some text after. Then I check that only the text before the call to End() is present in HttpResponseBase.Output.
The problem is, I can't figure out how to mock HttpResponseBase.End() so that it stops processing, like it does in ASP.NET.
public static HttpResponseBase CreateHttpResponseBase() {
var mock = new Mock<HttpResponseBase>();
StringWriter output = new StringWriter();
mock.SetupProperty(x => x.StatusCode);
mock.SetupGet(x => x.Output).Returns(output);
mock.Setup(x => x.End()) /* what do I put here? */;
mock.Setup(x => x.Write(It.IsAny<string>()))
.Callback<string>(s => output.Write(s));
return mock.Object;
}
It is a bit unclear to me what it is you are trying to achieve, but from your description, it sounds like you are attempting to get your Abstraction to behave like a particular implementation. In other words, because HttpResponse.End() has a certain behavior, you want your Mock to have the same behavior?
In general, that is not particularly easy to do with Moq, since it has no concept of ordered expectations (unlike RhinoMocks). There is, however, a feature request for it.
You might be able to use a Callback together with setting up the End method to toggle a flag that determines any further behavior of the Mock, but it's not going to be particularly pretty. I'm thinking about something like this:
bool ended = false;
var mock = new Mock<HttpResponseBase>();
mock.Setup(x => x.End()).Callback(() => ended = true);
// Other setups involving 'ended' and Callbacks
Then have all other Setups have dual implementatations based on whether ended is true or false.
It would be pretty damn ugly, so I'd seriously reconsider my options at this point. There are at least two directions you can take:
Make a Fake implementation of HttpResponseBase instead of using Moq. It sounds like you are expecting such specific behavior of the implementation that a Test Double with embedded logic sounds like a better option. Put shortly, a Fake is a Test Double that can contain semi-complex logic that mimics the intended production implementation. You can read more about Fakes and other Test Doubles in the excellent xUnit Test Patterns book.
Reconsider your initial assumptions. It sounds to me like you are tying your client very closely to a particular behavior of HttpResponseBase, so you may be violating the Liskov Substitution Principle. However, I may be mistaken, as a method called 'End' carries certain connotations beyond the purely semantic, but still, I'd personally consider if a better design was possible.
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.