I have an 'Example' class and I would like to create unit test for it. Take a look on my classes below:
public class Example
{
private readonly Calculator _calculator;
public Example(ICalculator calculator)
{
_calculator = calculator;
}
public void Calculate()
{
_calculator.Execute(operation => operation.Subtract());
}
}
public interface IOperation {
void Sum();
void Subtract();
}
public inferface ICalculator {
void Execute(Action<IOperation> action);
}
public class Calculator {
public void Execute(Action<IOperation> action){}
}
What I want is to create a Unit Test class to verify that my method from Example class Calculate
calls the _calculator.Execute
passing as parameter the operation.Subtract()
. Is it possible?
I know how to mock my ICalculator and verify that Execute
is being called once, but I have no idea how to validade if Execute
method was called using operation.Subtract()
as parameter instead of operation.Sum()
.
I am using NUnit
to create my unit tests. Here you can see how my unit test class is at the moment:
[TestFixture]
public class ExampleTests
{
[Test]
public void Test1()
{
var calculator = new Mock<ICalculator>();
var subject = new Example(calculator.Object);
subject.Calculate();
calculator.Verify(x => x.Execute(It.IsAny<Action<IOperation>>()), Times.Once);
}
}
Hope someone can understand my english, sorry about that.
You're passing anonymous delegate operation => operation.Subtract()
to _calculator.Execute
- so you cannot construct it later when asserting for argument.
You can get around it by doing this:
public class Example
{
private readonly ICalculator _calculator;
public Example(ICalculator calculator)
{
_calculator = calculator;
}
public Action<IOperation> Subtract = op => op.Subtract();
public Action<IOperation> Add = op => op.Sum();
public void Calculate()
{
_calculator.Execute(Subtract);
}
}
And asserting like this (ommiting 2nd param defaults to Once):
calculator.Verify(x => x.Execute(subject.Subtract));
However this looks like convoluted design in order to be able to write a test.
You cannot directly verify what lambda was passed but you can go around it by actually invoking said lambda with yet another mock:
var calculator = new Mock<ICalculator>();
var operation = new Mock<IOperation>();
// when calculator's Execute is called, invoke it's argument (Action<IOperation>)
// with mocked IOperation which will later be verified
calculator
.Setup(c => c.Execute(It.IsAny<Action<IOperation>>()))
.Callback<Action<IOperation>>(args => args(operation.Object));
var example = new Example(calculator.Object);
example.Calculate();
calculator.Verify(c => c.Execute(It.IsAny<Action<IOperation>>()));
operation.Verify(o => o.Subtract());
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.