ArrangeMock makes it possible to write mocking code using more descriptive method names than the ones provided by mocking frameworks.
For example, consider the following set up using Moq ...
var payrollSystemMock = new Mock<IPayrollSystem>();
payrollSystemMock.Setup(x => x.GetSalaryForEmployee(It.IsAny<string>()))
.Returns(5);
For veteran mockers this is probably self explanatory. But if you are new to Moq or mocking in general, this can take some getting used to. Especially, the It.IsAny<string>()
part where we want to
specify that we don't care about the input to the method.
We can do better. Using ArrangeMock, the same set up looks like so ...
var payrollSystemMock = new Mock<IPayrollSystem>();
payrollSystemMock.Arrange()
.SoThatWhenMethod(x => x.GetSalaryForEmployee(WithAnyArgument.OfType<string>()))
.IsCalled()
.ItReturns(5);
Or consider the following, more complex scenario - we need to set up a method to return a particular value and capture the arguments that were used to invoke this method. In Moq, this is usually done with a callback like so ...
var payrollSystemMock = new Mock<IPayrollSystem>();
string employeePassedToMethod = null;
payrollSystemMock.Setup(x => x.GetSalaryForEmployee(It.IsAny<string>()))
.Returns(5)
.Callback<string>(x => employeePassedToMethod = x);
Anyone who had to set up this scenario had to spend some time googling before discovering the "Callback" method and how it can be used. And any subsequent developer who hasn't seen the "Callback" method of Moq before will probably have to look it up as well.
The same set up in ArrangeMock looks like so ...
var payrollSystemMock = new Mock<IPayrollSystem>();
string employeePassedToMethod = null;
payrollSystemMock.Arrange()
.SoThatWhenMethod(x => x.GetSalaryForEmployee(WithAnyArgument.OfType<string>()))
.IsCalled()
.ItReturns(5)
.AndTheArgumentsPassedIn()
.AreSavedTo(() => employeePassedToMethod);
This is a lot more intuitive and easy to read.
With ArrangeMock, the unfamiliar Moq method names, It.IsAny() syntax and any other esoteric mocking setups are wrapped up in more descriptive and easy to read code.
While ArrangeMock wraps up the common mocking scenarios and patterns if you need to set up a scenario that is not aliased by ArrangeMock you still have the original Moq object which can be used as per normal.
Using ArrangeMock along with such wonderful libraries as Shouldly (which was the inspiration for this project) allows us to write descriptive tests that read like functional specifications of the application.
Method with more than one argument
Method was called at least x times
Method was called at least once
Method was called at most x times
Method was called at most once
Method was called between x and y times (inclusive)
Method was called between x and y times (exclusive)
Method was called exactly x times
Using arguments to invoke an action
Using multiple arguments to invoke an action
With ArrangeMock, a function that doesn't take any arguments and returns a value can be mocked like so ...
var payrollSystemMock = new Mock<IPayrollSystem>();
payrollSystemMock.Arrange()
.SoThatWhenMethod(x => x.GetNextPayDate())
.IsCalled()
.ItReturns(new DateTime(2014,11,11));
With ArrangeMock, a function that takes an argument of type string and returns a value can be mocked like so ...
var payrollSystemMock = new Mock<IPayrollSystem>();
payrollSystemMock.Arrange()
.SoThatWhenMethod(x => x.GetSalaryForEmployee(WithAnyArgument.OfType<string>()))
.IsCalled()
.ItReturns(5);
payrollSystemMock.Object.GetSalaryForEmployee("Foo").ShouldBe(5);
With ArrangeMock, a function that takes arguments of type string and int and returns a value can be mocked like so ...
var payrollSystemMock = new Mock<IPayrollSystem>();
payrollSystemMock.Arrange()
.SoThatWhenMethod(x => x.GetSalaryForEmployeeForYear(WithAnyArgument.OfType<string>(),
WithAnyArgument.OfType<int>()))
.IsCalled()
.ItReturns(6);
payrollSystemMock.Object.GetSalaryForEmployeeForYear("Foo", 2014).ShouldBe(6);
With ArrangeMock, the accessing of a property can be mocked like so ...
var payrollSystemMock = new Mock<IPayrollSystem>();
payrollSystemMock.Arrange()
.SoThatWhenProperty(x => x.IsOnline)
.IsAccessed()
.ItReturns(true);
With ArrangeMock, when a property is set, the value provided to the setter can be saved locally like so ...
var payrollSystemMock = new Mock<IPayrollSystem>();
bool boolPassedToSet = false;
payrollSystemMock.Arrange()
.SoThatWhenProperty(x => x.IsOnline)
.IsSet()
.ItIsSavedTo(() => boolPassedToSet);
In Moq, the "Verify" method is used to assert that a method was called on the mock. In ArrangeMock, this function is performed by the "Assert" method.
With ArrangeMock, given a method that doesn't take any parameters, we can confirm that it was called at least once like so ...
var payrollSystemMock = new Mock<IPayrollSystem>();
payrollSystemMock.Arrange()
.SoThatWhenMethod(x => x.GetNextPayDate())
.IsCalled()
.ItReturns(new DateTime(2014,11,11));
payrollSystemMock.Assert()
.ThatMethod(x => x.GetNextPayDate())
.WasCalled();
With ArrangeMock, given a method that doesn't take any parameters, we can confirm that it was called at least 3 times like so ...
var payrollSystemMock = new Mock<IPayrollSystem>();
payrollSystemMock.Arrange()
.SoThatWhenMethod(x => x.GetNextPayDate())
.IsCalled()
.ItReturns(new DateTime(2014,11,11));
payrollSystemMock.Assert()
.ThatMethod(x => x.GetNextPayDate())
.WasCalled()
.AtLeast(3)
.Times();
With ArrangeMock, given a method that doesn't take any parameters, we can confirm that it was called at least once like so ...
var payrollSystemMock = new Mock<IPayrollSystem>();
payrollSystemMock.Arrange()
.SoThatWhenMethod(x => x.GetNextPayDate())
.IsCalled()
.ItReturns(new DateTime(2014,11,11));
payrollSystemMock.Assert()
.ThatMethod(x => x.GetNextPayDate())
.WasCalled()
.AtLeastOnce();
With ArrangeMock, given a method that doesn't take any parameters, we can confirm that it was called at most 2 times like so ...
var payrollSystemMock = new Mock<IPayrollSystem>();
payrollSystemMock.Arrange()
.SoThatWhenMethod(x => x.GetNextPayDate())
.IsCalled()
.ItReturns(new DateTime(2014,11,11));
payrollSystemMock.Assert()
.ThatMethod(x => x.GetNextPayDate())
.WasCalledAtMost(2)
.Times();
With ArrangeMock, given a method that doesn't take any parameters, we can confirm that it was called at most once like so ...
var payrollSystemMock = new Mock<IPayrollSystem>();
payrollSystemMock.Arrange()
.SoThatWhenMethod(x => x.GetNextPayDate())
.IsCalled()
.ItReturns(new DateTime(2014,11,11));
payrollSystemMock.Assert()
.ThatMethod(x => x.GetNextPayDate())
.WasCalledAtMostOnce();
With ArrangeMock, given a method that doesn't take any parameters, we can confirm that it was called at least 2 and and no more than 3 times like so ...
var payrollSystemMock = new Mock<IPayrollSystem>();
payrollSystemMock.Arrange()
.SoThatWhenMethod(x => x.GetNextPayDate())
.IsCalled()
.ItReturns(new DateTime(2014,11,11));
payrollSystemMock.Assert()
.ThatMethod(x => x.GetNextPayDate())
.WasCalledBetween(2)
.And(3).TimesIncludingTheToAndFromValues();
With ArrangeMock, given a method that doesn't take any parameters, we can confirm that it was called more than 2 and less than 4 times like so ...
var payrollSystemMock = new Mock<IPayrollSystem>();
payrollSystemMock.Arrange()
.SoThatWhenMethod(x => x.GetNextPayDate())
.IsCalled()
.ItReturns(new DateTime(2014,11,11));
payrollSystemMock.Assert()
.ThatMethod(x => x.GetNextPayDate())
.WasCalledBetween(2)
.And(4).TimesExcludingTheToAndFromValues();
With ArrangeMock, given a method that doesn't take any parameters, we can confirm that it was called exactly 2 times like so ...
var payrollSystemMock = new Mock<IPayrollSystem>();
payrollSystemMock.Arrange()
.SoThatWhenMethod(x => x.GetNextPayDate())
.IsCalled()
.ItReturns(new DateTime(2014,11,11));
payrollSystemMock.Assert()
.ThatMethod(x => x.GetNextPayDate())
.WasCalled()
.Exactly(2)
.Times();
With ArrangeMock, given a method that doesn't take any parameters, we can confirm that it was never called like so ...
var payrollSystemMock = new Mock<IPayrollSystem>();
payrollSystemMock.Arrange()
.SoThatWhenMethod(x => x.GetNextPayDate())
.IsCalled()
.ItReturns(new DateTime(2014,11,11));
payrollSystemMock.Assert()
.ThatMethod(x => x.GetNextPayDate())
.WasNeverCalled();
With ArrangeMock, given a method that doesn't take any parameters, we can confirm that it was never called once like so ...
var payrollSystemMock = new Mock<IPayrollSystem>();
payrollSystemMock.Arrange()
.SoThatWhenMethod(x => x.GetNextPayDate())
.IsCalled()
.ItReturns(new DateTime(2014,11,11));
payrollSystemMock.Assert()
.ThatMethod(x => x.GetNextPayDate())
.WasCalled()
.Once();
In Moq, the "Callback" method is used to take the arguments that are passed in to a method and process them further. In ArrangeMock, this function is performed by the "TheArgumentsPassedIn" method.
With ArrangeMock, given a method that has one parameter, we can save the argument that was actually passed in like so ...
var payrollSystemMock = new Mock<IPayrollSystem>();
string passedInString = null;
payrollSystemMock.Arrange()
.SoThatWhenMethod(x => x.GetSalaryForEmployee(WithAnyArgument.OfType<string>()))
.IsCalled()
.TheArgumentsPassedIn()
.AreSavedTo(() => passedInString);
With ArrangeMock, given a method that has more than one parameter, we can save the argument that were actually passed in like so ...
var payrollSystemMock = new Mock<IPayrollSystem>();
string passedInString = null;
int passedInInt = 0;
payrollSystemMock.Arrange()
.SoThatWhenMethod(x => x.FinalisePaymentsForEmployeeForMonth(WithAnyArgument.OfType<string>(), WithAnyArgument.OfType<int>() ))
.IsCalled()
.TheArgumentsPassedIn()
.AreSavedTo(() => passedInString,
() => passedInInt);
With ArrangeMock, given a method that has one parameter, we can use the argument that was actually passed in to invoke an action like so ...
var payrollSystemMock = new Mock<IPayrollSystem>();
string passedInString = null;
payrollSystemMock.Arrange()
.SoThatWhenMethod(x => x.GetSalaryForEmployee(WithAnyArgument.OfType<string>()))
.IsCalled()
.TheArgumentsPassedIn()
.AreUsedToInvokeAction<string>(x => passedInString = x );
With ArrangeMock, given a method that has more than one parameter, we can use the arguments that were actually passed in to invoke an action like so ...
var payrollSystemMock = new Mock<IPayrollSystem>();
string passedInString = null;
int passedInInt = 0;
payrollSystemMock.Arrange()
.SoThatWhenMethod(x => x.GetSalaryForEmployeeForYear(WithAnyArgument.OfType<string>(), WithAnyArgument.OfType<int>()))
.IsCalled()
.TheArgumentsPassedIn()
.AreUsedToInvokeAction<string, int>((x, i) => { passedInString = x; passedInInt = i; });