2011-10-10 126 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是否正確執行。在服務層中,單元測試只需驗證是否使用正確的參數調用了存儲庫。