I'm using Moq framework and xUnit in .NET Core application. I have a mock of the repository
public interface IItemRepository<T>
{
string Add(T entity);
}
I want to test the method of the class, which is using this repository
public DefaultCartService(IItemRepository<CartItem> cartRepository)
{
_cartRepository = cartRepository;
}
public Task<GenericResponse<string>> AddItem(CartItem model)
{
var result = new GenericResponse<string>();
try
{
result.Response = _cartRepository.Add(cartItem);
}
catch(Exception ex)
{
result.Status = false;
result.Error = ex.Message;
}
return Task.FromResult(result);
}
This is a Generic Response Class to wrap repository result
public class GenericResponse<T>
{
public bool Status { get; set; } = true;
public T Response { get; set; }
public string Error { get; set;
}
}
This is how I preset Mock for the repository and calling the method
[Fact]
public void AddItem_WorkingTest()
{
//creating mock
var mock = new Mock<IItemRepository<CartItem>>();
//setting a method
mock.Setup(x => x.Add(new CartItem())).Returns("SomeGuidValue");
//creating input param
CartItemInputModelDTO inputModel = new CartItem() {BuyerId = "232", ProductId = "35435" };
//creating service class instance and passing repository mock
var _service = new DefaultCartService(_cartRepository.Object);
//calling method
var result = _service.AddItem(inputModel).Result.Response;
//verifying that mocks method been called
mock.Verify(x => x.Add(new CartItem()), Times.AtLeastOnce);
}
As a result, I get a failed test as repository never been called. And I don't understand why, since it I set there is nothing the stops method to be called Test result
Moq.MockException : Expected invocation on the mock at least once, but was never performed:
x => x.Add(CartItem)
Performed invocations:Mock<IItemRepository<CartItem>:2
(x): No invocations performed.
use It.IsAny<CartItem>()
in the setup. The current setup wont work because the instance passed in the test is not the instance used in the setup.
Also if testing a member that returns Task
derived result then make test async
[Fact]
public async Task AddItem_WorkingTest() {
//creating mock
var mock = new Mock<IItemRepository<CartItem>>();
//setting a method
mock.Setup(x => x.Add(It.IsAny<CartItem>())).Returns("SomeGuidValue");
//creating input param
var inputModel = new CartItem() {BuyerId = "232", ProductId = "35435" };
//creating service class instance and passing repository mock
var _service = new DefaultCartService(mock.Object);
//calling method
var result = await _service.AddItem(inputModel);;
//verifying that mocks method been called
mock.Verify(x => x.Add(It.IsAny<CartItem>()), Times.AtLeastOnce);
}
If you want to verify the members of the instance passed into the mock then use It.Is<CartItem>()
with a predicate
For example
//... omitted for brevity
mock.Verify(x => x.Add(It.Is<CartItem>(_ =>
_.BuyerId == inputModel.BuyerId
&& _.ProductId == inputModel.ProductId)), Times.AtLeastOnce);
Reference Moq Quickstart