代码之家  ›  专栏  ›  技术社区  ›  Cybercop

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

  •  0
  • Cybercop  · 技术社区  · 8 年前

    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 回复  |  直到 8 年前
        1
  •  2
  •   zaitsman    8 年前

    发生的事情(最有可能)是最小订货量不能匹配 Expression<Func<T, bool>> 当你做 .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()); 但是,如果没有调用它,那么capturedExpression为null(该技术称为隐式断言)