moq and parameters matching - c#

I'm struggeling with using moq and validating parameters passed to the methods of mocked interface. I have a code like:
MockRepository mockRepository = new MockRepository(MockBehavior.Default);
Mock<IConfigurationUpdater> workerInstanceMock = mockRepository.Create<IConfigurationUpdater>();
Mock<IConfiguration> configurationMock = mockRepository.Create<IConfiguration>();
configurationMock.Setup(t => t.Folder).Returns("Folder");
configurationMock.Setup(t => t.FileName).Returns("FileName");
workerInstanceMock
.Setup(
x => x.DoSomeWork(
It.Is<string>(
t => t == Path.Combine(configurationMock.Object.Folder, configurationMock.Object.FileName))))
.Verifiable("DoSomeWork not properly called");
mockRepository.VerifyAll();
The problem is that inside the lambda expresion generated for "It.Is", all properties of configurationMock (which were setup previously) are null. (if I would take that "Path.Combine" into a string, it would all work just fine).
In this exact case, the "Path.Combine" is failing because it received null parameters.
How should I properly use mocks and validate that my interface is called with the correct parameters.
Thanks,
florin

I think you need to use moq properties that will automatically start tracking its value (Stubs).
Instead of:
configurationMock.Setup(t => t.Folder).Returns("Folder");
configurationMock.Setup(t => t.FileName).Returns("FileName");
you can use
configurationMock.SetupProperty(t => t.Folder, "Folder");
configurationMock.SetupProperty(t => t.FileName, "FileName");
and then access the property as you did:
configurationMock.Object.Folder
More on moq properties can be found here: http://code.google.com/p/moq/wiki/QuickStart#Properties

Related

Mock SignalR hub for testing dependent class

I'm trying to instantiate a class that handles a bunch of functionality, and is constructed using dependency injection. I mock two of my parameters, and the third is an in-memory database context. Now when asserting, it's throwing an error on the mockClientProxyParticipants.Verify() line:
System.NotSupportedException : Invalid verify on an extension method: proxy => proxy.SendAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<CancellationToken>())
It is virtually impossible to not call the function, and calling Verify() with Times.Never() as parameter doesn't change anything.
I tried setting up the Linq argument of Verify() using normal strings like for mockClientProxyResults.Verify(), I tried using It.Is<string>(s => s == "some string") and I tried It.IsAny<string>().
I honestly don't understand what's wrong right now. Here's my test code, let me know if you want to see more:
var mockHub = new Mock<IHubContext<VoteHub>>();
var mockClients = new Mock<IHubClients>();
var mockClientProxyParticipants = new Mock<IClientProxy>();
var mockClientProxyResults = new Mock<IClientProxy>();
mockClients.Setup(clients => clients.Group("Participants")).Returns(mockClientProxyParticipants.Object);
mockClients.Setup(clients => clients.Group("Results")).Returns(mockClientProxyResults.Object);
mockHub.Setup(hub => hub.Clients).Returns(mockClients.Object);
var activeQuestionManagerMock = new Mock<IActiveQuestionManager>();
activeQuestionManagerMock.Setup(x => x.GetActiveQuestion())
.Returns(new ActiveQuestionModel(options));
QuestionHandler qm = new QuestionHandler(new VoteDbContext(options), mockHub.Object, activeQuestionManagerMock.Object);
//Act
qm.Ask(question);
//Assert
mockClientProxyParticipants.Verify(proxy => proxy.SendAsync(It.IsAny<string>(/*s => s == "AskQuestion"*/), It.IsAny<string>(/*s => s == qwaJSON*/), It.IsAny<CancellationToken>()), Times.Once());
mockClientProxyResults.Verify(proxy => proxy.SendAsync("UpdateCurrentQuestionProgress", It.IsAny<ActiveQuestionModel>(), default(CancellationToken)), Times.Once());
Turns out I misunderstood the error message and the issue is that IClientProxy.SendAsync() is an extension method, and Moq apparently doesn't like that. It's possible to use SendCoreAsync() instead, but you'll always have to pass an array as parameter, even if you want to send just one object or don't want to send any data at all.
credit to NKosi (see question comments)

How to Setup/Verify method call with specified parameter

I need to test if method GetKey(object target) was called with specified parameter. I know that verification can be called like
processor.Verify(x => x.GetKey(It.Is<object>(y => y == target)));
but how should setup look?
processor.Setup(x => x.GetKey(It.Is<object>(y => y == target)));
or
processor.Setup(x => x.GetKey(It.IsAny<object>()));
What is the difference in these 2 setups? Does it really matter in this case?
The processor interface:
public interface ILayoutProcessor
{
object GetKey(object target);
}
Just pass the specified parameter in the Setup or Verify method expression
processor.Setup(x => x.GetKey(target)).Verifiable();
and verify later
processor.Verify();
or
processor.Verify(x => x.GetKey(target), Times.AtLeastOnce);
processor.Setup(x => x.GetKey(It.Is<object>(y => y == target)));
Is a setup for when the method is called with an object matching the specified condition.
processor.Setup(x => x.GetKey(It.IsAny<object>()));
Is a setup that will match any object argument.
In your case, where you want to only verify that the method was called with a certain argument, it does not matter which setup you use. In fact, if the return value of your function is not used, you don't even need a setup to be able to verify. However in your case I assume you do since you mention Callback and Returns in the comments.
Note that you can shorten your verification to simply:
processor.Verify(x => x.GetKey(target));

Mock for several predicates

I create a mock object with one method
IMyIterface dosGuard = Mock.Of<IMyIterface >(
dg =>
dg.IsMethod1(It.IsAny<IPAddress>(), It.IsAny<string>(), It.IsAny<string>()) == false
);
I would like to specify the predicate for other method also :
dg.IsMethod2(It.IsAny<IPAddress>(), It.IsAny<string>(), It.IsAny<string>()) == false
How can I do it for both methods together?
Yes, you actually can factory build the entire object's structure with Mock.Of<T>() -- it just appears a little quirky at first:
interface IInterface
{
int IntMethod();
string StringMethod();
}
var instance = Mock.Of<IInterface>(ifc =>
ifc.IntMethod() == 1 &&
ifc.StringMethod() == "Hello");
It uses boolean as MemberAssignment, but aside from that, it would read get me a Mock of IInterface, with an IntMethod returning 1 and a StringMethod returning "Hello". Also the It.IsAny<TType>() for parameters works in the predicate, as well as nested Mock.Of<T> calls.
Once you get going though, it becomes much cleaner, and one can spin up static methods for assignment/updating root test scenarios : i.e. take 'optimal' model and tweak a few fields, without having to re-type the entire model.
If you want to setup multiple things on your mock object you can't* use the Mock.Of<T> factory method, you need to setup the mock object yourself:
var dosGuardMock = new Mock<IMyInterface>();
dosGuardMock.Setup(dg => dg.IsMethod1(It.IsAny<IPAddress>(), It.IsAny<string>(), It.IsAny<string>())).Returns(false);
dosGuardMock.Setup(dg => dg.IsMethod2(It.IsAny<IPAddress>(), It.IsAny<string>(), It.IsAny<string>())).Returns(false);
var dosGuard = dosGuardMock.Object;
*Alternatively, you can use the factory method, and use the static Mock.Get method to modify the instance created by the factory method:
var dosGuard = new Mock.Of<IMyInterface>();
Mock.Get(dosGuard).Setup(dg => dg.IsMethod1(It.IsAny<IPAddress>(), It.IsAny<string>(), It.IsAny<string>())).Returns(false);
Mock.Get(dosGuard).Setup(dg => dg.IsMethod2(It.IsAny<IPAddress>(), It.IsAny<string>(), It.IsAny<string>())).Returns(false);
However, I prefer the first example, because it draws an explicit difference between the Mock<T> instance and the "mock" T instance.

Can I test method call order with AAA syntax in Rhino-Mocks 3.6?

Is it possible to test for the following example if the Method1 called 1st, then Method2 called after and then Method3 by using the AAA syntax, in Rhino-mocks 3.6 ?
// Assert
var mock = MockRepository.GenerateMock<ISomeService>();
// Act
myObject.Service = mock;
// How should I change this part to ensure that Rhino Mocks check the call order as well?
mock.AssertWasCalled(m=>m.Method1());
mock.AssertWasCalled(m=>m.Method2());
mock.AssertWasCalled(m=>m.Method3());
Here's one way to do it...
mock.AssertWasCalled(m=>m.Method1(), options => options.WhenCalled(w => mockService.AssertWasNotCalled(x=>x.Method2())));
mock.AssertWasCalled(m=>m.Method2(), options => options.WhenCalled(w => mockService.AssertWasNotCalled(x=>x.Method3())));
mock.AssertWasCalled(m=>m.Method3());
You can, but you really shouldn't. You should focus on testing the externall observable behaviors, rather than the implementation.
Method call order can change without affecting the contract with the client of the API. In that case, your test will fail, even when it shouldn't.
In short, testing implementation leads to brittle tests. Brittle tests lead to abandonment of the tests. You don't want to go there.
Hope this helps.
Here is how to do it nicely.
var mocks = new MockRepository();
var fooMock = mocks.DynamicMock<IFoo>();
using (mocks.Ordered())
{
fooMock.Expect(x => x.Method1());
fooMock.Expect(x => x.Method2());
}
fooMock.Replay();
var bar = new Bar(fooMock);
bar.DoWork();
fooMock.VerifyAllExpectations();
Found the answer from this blog post: Verifying the Order Of Method Execution With Rhino Mocks 3.5 by Philip Japikse
Here's how to do it by building assertions into each method invocation.
// Arrange - Build the necessary assertions into the stubbed method invocations.
var mock = MockRepository.GenerateMock<ISomeService>();
mock.Stub(m => m.Method1()).WhenCalled(inv => mock.AssertWasNotCalled(m => m.Method2()));
mock.Stub(m => m.Method2()).WhenCalled(inv => mock.AssertWasNotCalled(m => m.Method3()));
// Act
myObject.Service = mock;
// Assert - Ensure each expected method was called.
mock.AssertWasCalled(m => m.Method1());
mock.AssertWasCalled(m => m.Method2());
mock.AssertWasCalled(m => m.Method3());
Since this is mixes up normal arrange-act-assert pattern by running assertions in mid-act, I like to include very specific error messages for these instances to identify test failures more easily.
mock.Stub(m => m.Method1()).WhenCalled(inv =>
mock.AssertWasNotCalled(m => m.Method2(), opt =>
opt.Message("Method2 cannot be called before Method1.")));
You could also achieve a similar result by saving the result of each invocation in a variable during the act step, and then checking the variable states during the assert step. This better preserves the division of the arrange-act-assert pattern, but it is more plumbing code to write and maintain.
// Arrange - Build the necessary state variables into the stubbed method invocations.
bool wasMethod1Called;
bool wasMethod2Called;
bool wasMethod2CalledBeforeMethod1;
bool wasMethod3CalledBeforeMethod2;
var mock = MockRepository.GenerateMock<ISomeService>();
mock.Stub(m => m.Method1()).WhenCalled(inv =>
{
wasMethod1Called = true;
});
mock.Stub(m => m.Method2()).WhenCalled(inv =>
{
wasMethod2Called = true;
wasMethod2CalledBeforeMethod1 = !wasMethod1Called;
});
mock.Stub(m => m.Method3()).WhenCalled(inv =>
{
wasMethod3CalledBeforeMethod2 = !wasMethod2Called;
});
// Act
myObject.Service = mock;
// Assert - Ensure each expected method was called, and that they were called in the right order.
mock.AssertWasCalled(m => m.Method1());
mock.AssertWasCalled(m => m.Method2());
mock.AssertWasCalled(m => m.Method3());
Assert.That(wasMethod2CalledBeforeMethod1, Is.False, "Method2 cannot be called before Method1.");
Assert.That(wasMethod3CalledBeforeMethod2, Is.False, "Method3 cannot be called before Method2.");
The mocks.Ordered() syntax specified by #craastad is the right way to do it, but I couldn't get it to work in RhinoMocks 3.5 - instead I had to tweak it to work without the instance of MockRepository that #craastad's solution used to call Ordered() on:
var fooMock = MockRepository.GenerateMock<IFoo>();
using (fooMock.GetMockRepository().Ordered())
{
fooMock.Expect(x => x.Method1());
fooMock.Expect(x => x.Method2());
}
var bar = new Bar(fooMock);
bar.DoWork();
fooMock.VerifyAllExpectations();
If you do it this way, it also appears to be unnecessary to call fooMock.Replay() either.

Moq does It.Is<List<List<string>>>(x => x.Count == 10) do what I think it should do?

I am passing this into the constructor of an object I am unit testing
It.Is<List<List<string>>>(x => x.Count == 10)
but when I step into the constructor, this statement resolves to null instead of a a List<List<string>> with a Count of 10. Am I misunderstanding how this works?
The It.Is method is not meant to be called. Actually, I think it should just throw, instead of returning the default value of the type.
It is meant to be used in the expression trees used to setting expectations:
interface IFoo { bool DoSomething(IList<IList<string>> strings); }
var mock = new Mock<IFoo>();
mock.Setup(f => f.DoSomething(It.Is<IList<IList<string>>>(l => l.Count == 10))
.Returns(true);
The example sets up a mock object of IFoo that will return true when passed an IList<IList<string>> object with 10 elements. This means that after the following call, result will be true:
IList<IList<string>> listWith10Elements = // create a list with 10 elements
bool result = mock.Object.DoSomething(listWith10Elements);
If you're passing something into the constructor of an object, you would normally use the proxy object from a mock, with Setup on that mock providing any context which your class needs.
For instance:
var mock = new Mock<List<List<string>>>();
mock.Setup(x => x.Count()).Returns(10);
var myClass = new MyClass(mock.Object);
Use Verify to check interactions. What you have there is a matcher, which you can use in Setup and Verify to match particular types of arguments.
Except, of course, that you won't be able to mock List because it doesn't have the virtual methods you're after. Try using, and mocking, ICollection<List<string>> instead.
I think this should do what you want. Hope this helps.

Categories

Resources