Reputation: 7657
I am trying to test my delete method for my service, to do this I am trying to add an item to the repository first. However, I don't think my mock repository add method is being called because _mockRepository.Object.GetAll()
is always null. I have tried stepping in with the debugger and it just skips over it too. What am I doing wrong?
public class CommentServiceTest
{
private Mock<IRepository<Comment>> _mockRepository;
private ICommentService _service;
private ModelStateDictionary _modelState;
public CommentServiceTest()
{
_modelState = new ModelStateDictionary();
_mockRepository = new Mock<IRepository<Comment>>();
_service = new CommentService(new ModelStateWrapper(_modelState), _mockRepository.Object);
}
[Fact]
public void Delete()
{
var comment = new Comment("BodyText")
{
Audio = new Audio(),
Date = DateTime.Now
};
_mockRepository.Object.Add(comment);
//Nothing in repository collection here still
var commentToDelete = _mockRepository.Object.GetAll().First();
_service.Delete(commentToDelete);
Assert.DoesNotContain(commentToDelete, _mockRepository.Object.GetAll());
}
}
public class Repository<T, TC> : IRepository<T> where T : class where TC : DbContext
{
private bool _disposed;
protected TC Context { get; }
public Repository()
{
}
public Repository(TC context)
{
Context = context;
}
public virtual IQueryable<T> GetAll()
{
return Context.Set<T>();
}
public virtual void Add(T entity)
{
Context.Set<T>().Add(entity);
Save();
}
public virtual void Save()
{
Context.SaveChanges();
}
}
}
Upvotes: 1
Views: 10829
Reputation: 388383
Your repository is a mock, so it does not contain any actual behavior by default. You first have to set up the mock to accept method calls on the mocked object. So in your case, you would first have to tell the mock to handle adds in some way (in addition to the deletes).
However, since you actually just want to test the service that deletes something from the service, you don’t need to add an object to the mock repository first. You actually just need to check whether the item is properly deleted from the mock repository. I.e. since the repository is a mock, you don’t need to really add something in order to delete it.
Your test should look like this:
[Fact]
public void Delete()
{
// arrange
var comment = new Comment("BodyText")
{
Audio = new Audio(),
Date = DateTime.Now
};
// set up the repository’s Delete call
_mockRepository.Setup(r => r.Delete(It.IsAny<Comment>()));
// act
_service.Delete(comment);
// assert
// verify that the Delete method we set up above was called
// with the comment as the first argument
_mockRepository.Verify(r => r.Delete(comment));
}
Also, I don’t know why the service handles the model state (and not the repository), but you should probably add an additional assert that the state was properly updated for the object too.
Upvotes: 10
Reputation: 52818
You are mocking out all of the methods on the IRepository<T>
interface, but are not telling the mocked version what to do when Add
or GetAll
are called.
You need something like this:
_mockRepository
.Setup(r => r.Add(It.IsAny<Comment>()))
.Callback(c => _service.Add(c));
_mockRepository
.Setup(r => r.GetAll())
.Returns(_service.GetAll());
This (or something similar) will means Add
puts things into your list, and GetAll
returns what is in your list.
Alternatively, you could try adding the Comment into the service
directly instead of into the repository. Without seeing how service is implemented, I can only guess though how this would work.
Upvotes: 3