Reputation: 9360
I am having the a typical CRUD operation interface (repository) and i was wondering how would someone test it using MOQ
.
Model
public class Model
{
public int Id{get;set;}
}
Interface
public interface ICrud
{
Task<IEnumerable<Model>> GetAllAsync();
Task AddAsync(Model model);
}
Service
public class Service
{
public ICrud operations;
Service(ICrud crud){ this.operations=crud;}
public Task<IEnumerable<Model>> GetAllAsync()=>this.operations.GetAllAsync();
public Task AddAsync(Model model)=> this.operations.AddAsync(model);
}
Unit Test
public class Test
{
public IEnumerable Seed(){
yield return new Model {id=3};
yield return new Model {id =4};
}
[Testcase(3)]
public async Task CanAdd(int id)
{
var mock=new Mock<ICrud>();
var newModel=new Model{ Id=id};
mock.Setup(x=>x.GetAsync()).ReturnsAsync(Seed);
mock.Setup(x=>x.AddAsync(newModel));
//how can i test adding the new model
var service=new Service(mock.Object);
var initialList=await service.GetAllAsync();
//adding
await service.AddAsync(newModel);
var finalList=await service.GetAllAsync();
}
}
My question is , how can i test the following scenario:
-i check the initial collection
-i call `AddAsync`
-i check to see that the new collection contains the added element.
How can this be achieved with Moq
in a unit test?
Upvotes: 0
Views: 1518
Reputation: 32455
Or you can do it without mocking frameworks.
public class InMemoryCrud : ICrud
{
public List<Model> Models { get; set; } = new List<Model>();
public Task<IEnumerable<Model>> GetAllAsync() => return Task.FromResult(Models);
public Task AddAsync(Model model)
{
Models.Add(model);
return Task.CompletedTask;
}
}
public async Task Add_Model()
{
var fakeCrud = new InMemoryCrud();
var service = new Service(fakeCrud);
var newModel = new Model { Id = 3 };
await service.AddAsync(newModel);
var actualModels = await fakeCrud.GetAllAsync();
var expected = new[]
{
new Model { Id = 3 }
}
actualModels.Should().BeEquivalentTo(expected); // Pass
}
With InMemoryCrud
implementation you can test that correct values ahs been "saved" via crud operations.
With mocking frameworks you will test that correct methods has been called. For example if in Service
class I change some properties of the given instance of the Model
- tests still pass, but wrong data will be saved to the database in real application.
Upvotes: 1
Reputation: 247153
In this scenario, pass case is that the subject service under test correctly invokes the dependency operation with the given model.
The test should thus reflect that when being exercised.
Using MOQ that would look like
public async Task Service_Should_AddAsync() {
//Arrange
int id = 1;
var mock = new Mock<ICrud>();
var newModel = new Model { Id = id };
mock.Setup(x => x.AddAsync(It.IsAny<Model>())).Returns(Task.CompletedTask);
var service = new Service(mock.Object);
//Act
await service.AddAsync(newModel);
//Assert
//verify that the mock was invoked with the given model.
mock.Verify(x => x.AddAsync(newModel));
}
Upvotes: 1