2011-10-10 127 views
1

我想通过我的服务层使用Moq来测试在我的存储库上使用的lambda。单元测试ServiceLayer与lambda和Moq

的服务:

public class CompanyService : TuneUpLog.ServiceLayer.ICompanyService 
{ 
    private IRepository<Company> _repository; 
    private IValidationDictionary _validatonDictionary; 
    private Guid _userId; 

    public CompanyService(Guid userId,IValidationDictionary validationDictionary, ObjectContext context) 
     : this(userId, validationDictionary, new Repository<Company>(context)) 
    { 
    } 

    public CompanyService(Guid userId, IValidationDictionary validationDictionary, IRepository<Company> repository) 
    { 
     _validatonDictionary = validationDictionary; 
     _repository = repository; 

     if (userId == Guid.Empty) 
      throw new SecurityException("UserId is required"); 
     else 
      _userId = userId; 
    } 

    public IEnumerable<Company> ListCompany() 
    { 
     return _repository.Find(c => c.Users.Any(u => u.UserId == _userId)); 
    } 
} 

测试:

[TestMethod] 
    public void ListCompany_1Valid1Invalid_ReturnsValidCompany() 
    { 
     Mock<IRepository<Company>> fakeCompanyRepository = new Mock<IRepository<Company>>(); 

     CompanyService companyService = new CompanyService(USER_ID, new ModelStateWrapper(_modelState), fakeCompanyRepository.Object); 

     //1 company for this user and 1 that isn't for this user 
     List<Company> companies = new List<Company>() 
      { 
       new Company() { Id = 1, Name = "Test Company", AccountTypeId = 1, Users = { new User() { UserId = USER_ID } } }, 
       new Company() { Id = 2, Name = "2nd Test Company", AccountTypeId = 1, Users = { new User() { UserId = Guid.Empty } } } 
      }; 

     fakeCompanyRepository.Setup(c => c.Find(It.IsAny<Expression<Func<Company, bool>>>())).Returns(companies.AsQueryable()); 

     //count should be 1 
     Assert.AreEqual(1, companyService.ListCompany().Count()); 
    } 

资源库:

public interface IRepository<T> where T : class, IEntity 
{ 
    void Add(T newEntity); 
    void Edit(T entity); 
    IQueryable<T> Find(Expression<Func<T, bool>> predicate); 
    IQueryable<T> FindAll(); 
    T FindById(int id); 
    void Remove(T entity); 
    void Attach(T entity); 
} 

测试是两家公司回归,而不是第一个公司,我期待。我究竟做错了什么?

+0

当你把一个放在ListCompany()方法中时,断点会告诉你什么? –

+0

由于存储库被嘲笑,ListCompany方法中的断点并没有给我多少提示。下面是对资源库中的模拟信息,但它似乎并不像这将是多大的帮助:\t \t行为\t宽松\t Moq.MockBehavior \t \t CallBase \t假\t布尔 \t \t默认值\t空\t Moq.DefaultValue –

+0

没错,所以如果存储库被嘲弄......我认为用户标识上的过滤器没有得到应用似乎是合乎逻辑的。 –

回答

4

我们使用相同的技术。您可以在设置模拟时捕获正在传递的表达式,如

fakeCompanyRepository.Setup(
    u => u.Find(It.IsAny<Expression<Func<Company, bool>>>())) 
    .Returns(
    //Capture the It.IsAny parameter 
    (Expression<Func<Company, bool>> expression) => 
    //Apply it to your queryable. 
     companies.AsQueryable().Where(expression)); 

这会将您的表达式应用于公司集合。

+0

这确实有用,但对我来说感觉有点不好意思。在内存中实现一个存储列表的虚假存储库并将其与服务层一起使用会更正确吗? –

+0

您在技术上正在制造一个虚假的存储库。但是,如果您查看我的IRepository/IUnitOfWork组合,我有一个用于测试的InMemoryUnitOfWork。 http://azurecoding.net/blogs/brownie/archive/2010/09/22/irepository-lt-t-gt-and-iunitofwork.aspx –

0

你设置你的模拟查找方法返回两个对象的列表,提供的拉姆达内部的用户id检查是通过这种设置

1

你的模拟库已经建立,返回这两个公司绕过,这就是为什么你让他们都回来。

您应该为存储库编写单元测试以检查lambda是否正确执行。在服务层中,单元测试只需验证是否使用正确的参数调用了存储库。