Is there any better way of writing this test with Moq? - c#

I have a private method which is being called in a method I am testing.I want to verify the correct parameters are being passed to this private method. I have written the following setup in Moq which will test what I want, however it doesn't really allow me to follow the Arrange, Act, Assert pattern.
Is there any way I can perform a similar test where by the assert can appear with all of my other asserts? At the moment the code below lives within the Arrange.
myClass.Setup(
x =>
x.myMethod(
It.IsAny<Person>>(),
It.IsAny<string>(),
It.IsAny<Person>(),
It.IsAny<ICollection<string>>(),
It.IsAny<ICollection<string>>(),
It.IsAny<bool>())).Callback
<Person, string, Person, Person, ICollection<string>, bool>(
(a, b, c, d, e, f) =>
{
Assert.AreEqual("NameA", a.Name);
Assert.AreEqual("StringB", b);
Assert.AreEqual("NameC", c.Name);
Assert.AreEqual(2, d);
var dList = d.ToList().OrderBy(x => x.Name);
Assert.AreEqual("PersonA", dList[0].Name)
Assert.AreEqual("PersonB", dList[1].Name);
});
I should say, I am aware that you can perfom a verify to check whether a method has been called with certain inputs, however I am not aware of any way of matching the ICollection params.

If you are using those assertions to check the parameters, you can do it in your setup. If your mock uses strict behavior, it will fail if a parameter doesn't match the predicate.
// declare your mock with strict behavior
myClass.Setup(
x =>
x.myMethod(
It.Is<Person>(person => person.Name == "NameA"),
"Stringb",
It.Is<Person>(person => person.Name == "NameC"),,
It.Is<ICollection<string>>(coll =>{
//your other validations
}),
It.IsAny<ICollection<string>>(),
It.IsAny<bool>()));

Purpose of unit tests is to verify that your class behaves as expected. You should exercise class via its public interface and check following things:
class state changes
returned results
calls to dependencies
Other stuff has no value while class behaves as expected. You can refactor your class and make that private method in-line.

Related

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 and parameters matching

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

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