Moq测试删除方法

时间:2016-07-24 21:11:28

标签: c# unit-testing moq

我正在尝试为我的服务测试我的删除方法,为此我尝试首先将项添加到存储库。但是,我不认为我的模拟存储库添加方法被调用,因为_mockRepository.Object.GetAll()始终为空。我试过插入调试器,它也只是跳过它。我做错了什么?

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();
    }   
}

}

2 个答案:

答案 0 :(得分:5)

您的存储库是模拟,因此默认情况下它不包含任何实际行为。首先必须设置模拟以接受对模拟对象的方法调用。因此,在您的情况下,您首先必须告诉模拟以某种方式处理添加(除了删除)。

但是,由于您实际上只想测试从服务中删除某些内容的服务,因此您无需先将对象添加到模拟存储库中。实际上,您只需要检查项目是否已从模拟存储库中正确删除。即由于存储库是模拟的,因此您无需真正添加某些内容即可将其删除。

您的测试应如下所示:

[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));
}

另外,我不知道为什么服务处理模型状态(而不是存储库),但你应该添加一个额外的断言,即对象也正确地更新了状态。

答案 1 :(得分:3)

您正在嘲笑IRepository<T>界面上的所有方法,但没有告诉模拟版本在调用AddGetAll时要执行的操作。

你需要这样的东西:

_mockRepository
.Setup(r => r.Add(It.IsAny<Comment>()))
.Callback(c => _service.Add(c));

_mockRepository
.Setup(r => r.GetAll())
.Returns(_service.GetAll());

此(或类似内容)意味着Add会将内容放入您的列表中,GetAll会返回列表中的内容。

或者,您可以尝试直接将注释添加到service而不是存储库中。在没有看到如何实现服务的情况下,我只能猜测它是如何工作的。