dinsdag 13 december 2016

How to express an expected call on a Moq mock in the memberdata for an XUnit Theory.

In XUnit you can use the [Theory] attribute to run the same test against a set of different parameters. Moq allows you to specify expectations on which methods of a mocked interface are called, with the Verify method. Recently, I wanted to combine these two techniques to be able to convey the expectation along with the other test parameters to the XUnit Theory. It took me a little thought to get this right. The trick is in casting the expected call (usually an Action<T>) to an Expression<Action<T>>. That is done in the gist below.
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using Moq;
using Xunit;
namespace DynamicVerify
{
public class ExpectedCallFromMemberData
{
[Theory]
[MemberData(nameof(GetMemberData))]
public void Bar_calls_right_method_on_IFoo(int number, Expression<Action<IFoo>> expectedCall, Times times, string message)
{
var fooMock = new Mock<IFoo>();
var sut = new Bar(fooMock.Object);
sut.DoBar(number);
fooMock.Verify(expectedCall, times, message);
}
private static IEnumerable<object[]> GetMemberData()
{
Func<Expression<Action<IFoo>>, Expression<Action<IFoo>>> fooCall = action => action;
return new List<object[]> {
new object[] {1, fooCall(foo => foo.DoFoo1()), Times.Once(), "Expected call on DoFoo1." },
new object[] {2, fooCall(foo => foo.DoFoo2()), Times.Once(), "Expected call on DoFoo2." },
new object[] {3, fooCall(foo => foo.DoFoo1()), Times.Never(), "Argument 3 should not call IFoo at all." },
};
}
}
public interface IFoo
{
void DoFoo1();
void DoFoo2();
}
public class Bar
{
private IFoo _foo;
public Bar(IFoo foo)
{
_foo = foo;
}
public void DoBar(int number)
{
if (number == 1)
_foo.DoFoo1();
else if (number == 2)
_foo.DoFoo2();
}
}
}

Geen opmerkingen: