验证服务调用IGenericRepository中定义的IRepository方法

时间:2018-08-29 12:58:34

标签: c# unit-testing moq

我有一个服务,例如Foo服务类。

public class FooService : IFooService
{
    private readonly IFooRepository _repository;
    private readonly ISomeService _eventService;

    public FooService(IFooRepository repository, ISomeService eventService)
    {
        _repository = repository;
        _someService = someService;
    }

    public IReadOnlyCollection<Foo> GetFoos(bool isDeleted = true)
    {
        var foos= _repository.GetList(x => x.IsDeleted == isDeleted).ToList();
        return !foos.Any() ? new List<Foo>(): foos;
    }

}

这里是IFooRepository

public interface IFooRepository : IGenericRepository<Foo>
{

}

这是IGenericRepository

public interface IGenericRepository<T> where T: BaseEntity
{

    IReadOnlyCollection<T> GetList(Expression<Func<T, bool>> where, params Expression<Func<T, object>>[] nav);

}

在测试中,我想验证FooService的GetFoos方法是否调用GetList方法

这是我尝试过的

[TestClass]
public class FooServiceTest
{
    private IQueryable<Foo> _foos;
    private Mock<IFooRepository> _fooRepository;
    private FooService _fooService;
    private Mock<ISomeService> _someService;
    [TestInitialize]
    public void SetUp()
    {

        _foos = new List<Foo>
        {
            new Foo
            {                  
                EmailId = "a@a.com",                  
                IsDeleted = false,                 
            },
            new Foo
            {                  
                EmailId = "a@a.com",                  
                IsDeleted = true,                 
            },       
        }.AsQueryable();           
    }

    [TestMethod]
    public void GetGetFoos_CallsGetList()
    {
        //Arrange
        var foos= _foos.Where(x => x.IsDeleted).ToList();    
        _fooRepository = new Mock<IFooRepository>();         
        _fooRepository.Setup(m => m.GetList(x => x.IsDeleted)).Returns(foos);
        _someServiceMock = new Mock<ISomeService>();
        _fooService = new FooService(_fooRepository.Object, _someServiceMock.Object);
        //Act
        _fooService.GetFoos(true);

        //Assert
        _fooRepository.Verify(m=>m.GetList(x=>x.IsDeleted), Times.Once());

    }
}

但是我在下一行得到参数null异常

var foos= _repository.GetList(x => x.IsDeleted == isDeleted).ToList();

即使在安装过程中我说Returns(foos),也仍然会出现这种情况。

我又如何验证接口方法被调用?

1 个答案:

答案 0 :(得分:2)

正在发生(很有可能)是,当您执行Expression<Func<T, bool>>时,Moq无法匹配.Setup()

因此,您可以使用IsAny<>()方法:

_fooRepository.Setup(m => m.GetList(It.IsAny<Expression<Func<Foo, bool>>>())).Returns(foos);

如果要断言传入的表达式,请尝试

Expression<Func<Foo, bool>> capturedExpression = null; 
_fooRepository.Setup(m => m.GetList(It.IsAny<Expression<Func<Foo, bool>>>()))
.Returns((Expression<Func<Foo, bool>> e ) => { capturedExpression = e; return foos; }); 
Assert.IsTrue(capturedExpression.Compile()(_foos[1])); 
Assert.IsFalse(capturedExpression.Compile()(_foos[0]));

要验证该方法是否被调用,您还可以将其更改为更多一点:

_fooRepository.Setup(m => m.GetList(It.IsAny<Expression<Func<Foo, bool>>>()))
.Returns((Expression<Func<Foo, bool>> e ) => { capturedExpression = e; return foos; })
.Verifiable(); 

然后_fooRepository.Verify(m=>m.GetList(It.IsAny<Expression<Func<Foo, bool>>>()), Times.Once());,但是,如果未调用它,则captureExpression为空(该技术称为隐式断言)