2012-01-11 83 views
1

問題:直接運行代碼會創建適當的過濾,並且我的單元測試根本不會過濾(返回模擬存儲庫中的所有記錄)。通過Moq測試表達式樹方法不使用表達式邏輯

我不知道在測試中是否有表達式邏輯是否搞砸了什麼或者什麼,但不管我設置的標準如何,模擬存儲庫不會在廣告上過濾我可以備份「所有」記錄。這從服務層調用它100%,但不是在測試中。

編輯:抱歉格式化的代碼,我無法得到它更好。

代碼

public abstract class EFRepository<T> : IRepository<T> where T : BaseEFModel { 

public IUnitOfWork UnitOfWork { get; set; } 

private IDbSet<T> _objectset; 
private IDbSet<T> ObjectSet 
{ 
    get { return _objectset ?? (_objectset = UnitOfWork.Context.Set<T>()); } 
} 

public virtual IQueryable<T> WhereInternal(Expression<Func<T, bool>> expression) 
{ 
    return ObjectSet.Where(expression); 
} } 

實現:

public class DoNotSolicitRepo : EFRepository<DoNotSolicit>, IDoNotSolicitRepo { 
private readonly RestUnitOfWork worker; 

public DoNotSolicitRepo(RestUnitOfWork _worker) 
{ 
    worker = _worker; 
} 

public IList<DNSContract> SelectWithCriteria(DNS_Search search) 
{ 
    // create the where clause 
    Expression<Func<DoNotSolicit, bool>> whereClause = c => (
     (String.IsNullOrEmpty(search.FirstName) || c.FirstName.StartsWith(search.FirstName)) && 
     (String.IsNullOrEmpty(search.LastName) || c.LastName.StartsWith(search.LastName)) && 
     (String.IsNullOrEmpty(search.Address1) || c.Address1.Contains(search.Address1)) && 
     (String.IsNullOrEmpty(search.Address2) || c.Address2.Contains(search.Address2)) && 
     (String.IsNullOrEmpty(search.City) || c.City.Contains(search.City)) && 
     (String.IsNullOrEmpty(search.State) || c.State.Equals(search.State)) && 
     (String.IsNullOrEmpty(search.Zip5) || c.Zip.Equals(search.Zip5)) && 
     (String.IsNullOrEmpty(search.Phone) || c.Phone.Equals(search.Phone)) && 
     (String.IsNullOrEmpty(search.Email) || c.Email.Equals(search.Email)) 
     ); 

    using (var scope = worker) 
    { 
     scope.Register(this); 
     var resultList = WhereInternal(whereClause).ToList(); 

     Mapper.CreateMap<DoNotSolicit, DNSContract>() 
      .ForMember(dest => dest.PartnerCode, opt => opt.Ignore()) 
      .ForMember(dest => dest.PartnerDescription, opt => opt.Ignore()) 
      .ForMember(dest => dest.DoNotSolicitReason, opt => opt.Ignore()) 
      .ForMember(dest => dest.SaveDate, opt => opt.Ignore()) 
      .ForMember(dest => dest.InsertDT, opt => opt.Ignore()); 

     var returnObj = Mapper.Map<IList<DoNotSolicit>, IList<DNSContract>>(resultList); 

     return returnObj.FriendlySaveDates(); 
    } 
} } 

測試

基地:

public abstract class BaseEFUnitFixture<T> where T : BaseEFModel { 
protected Mock<EFRepository<T>> mockedEFRepo = new Mock<EFRepository<T>>(); 

public Mock<EFRepository<T>> MockedEFRepositiory() 
{ 
    var t = new List<T>(); 

    mockedEFRepo.Setup(x => x.AddInternal(It.IsAny<T>())).Callback((T e) => t.Add(e)); 
    mockedEFRepo.Setup(x => x.AddInternal(It.IsAny<List<T>>())).Callback((IList<T> le) => t.AddRange(le)); 
    mockedEFRepo.Setup(x => x.AllInternal()).Returns(t.AsQueryable()); 
    mockedEFRepo.Setup(x => x.WhereInternal(It.Is<Expression<Func<T, bool>>>(y => y != null))).Returns(t.AsQueryable()); 

    return mockedEFRepo; 
} 

}

實現:

[TestFixture] public class DNSRepoTest : BaseEFUnitFixture<DoNotSolicit> { 
private readonly List<DoNotSolicit> list = new List<DoNotSolicit>(); 

private class Search 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public string Address1 { get; set; } 
    public string Address2 { get; set; } 
    public string City { get; set; } 
    public string State { get; set; } 
    public string Zip5 { get; set; } 
    public string Phone { get; set; } 
    public string Email { get; set; } 
} 

private Expression<Func<DoNotSolicit, bool>> SearchBuilder(Search search) 
{ 
    // same as repo logic 
    Expression<Func<DoNotSolicit, bool>> whereClause = c => (
     (String.IsNullOrEmpty(search.FirstName) || c.FirstName.StartsWith(search.FirstName)) && 
     (String.IsNullOrEmpty(search.LastName) || c.LastName.StartsWith(search.LastName)) && 
     (String.IsNullOrEmpty(search.Address1) || c.Address1.Contains(search.Address1)) && 
     (String.IsNullOrEmpty(search.Address2) || c.Address2.Contains(search.Address2)) && 
     (String.IsNullOrEmpty(search.City) || c.City.Contains(search.City)) && 
     (String.IsNullOrEmpty(search.State) || c.State.Equals(search.State)) && 
     (String.IsNullOrEmpty(search.Zip5) || c.Zip.Equals(search.Zip5)) && 
     (String.IsNullOrEmpty(search.Phone) || c.Phone.Equals(search.Phone)) && 
     (String.IsNullOrEmpty(search.Email) || c.Email.Equals(search.Email)) 
     ); 

    return whereClause; 
} 

[TestFixtureSetUp] 
public void Init() 
{ 
    list.Add(new DoNotSolicit 
       { 
        DoNotSolicitID = 4, 
        FirstName = "nunit", 
        Origination = "testing" 
       }); 

    mockedEFRepo = MockedEFRepositiory(); 
    mockedEFRepo.Object.AddInternal(list); 
} 

[Test] 
public void SelectWithCriteria_FirstNameMatch() 
{ 
    var clause = SearchBuilder(new Search{FirstName = "test"}); 
    var results = mockedEFRepo.Object.WhereInternal(clause).ToList(); 

    Assert.IsNotNull(results); 
    Assert.IsTrue(results.Count < mockedEFRepo.Object.AllInternal().Count()); 
    Assert.IsTrue(results.Count > 0); 
} } 

回答

1

你錯了,與一般的方法。你做什麼你嘲笑你測試的班 - 這是不正確的。你只應該嘲笑你正在測試的類外部的東西 - 因爲嘲笑所做的幾乎是用空存根代替模擬對象的功能。如果它被嘲笑,它不起作用或工作,因爲模擬配置。

我看不出爲什麼要測試模擬類,因爲在這種情況下,您測試的不是類功能/代碼,而是您配置模擬的方式。

很難理解你想要測試方法測試的代碼。我會建議做依賴注入來分隔實際的數據存儲庫(可以用特定的數據/方法模擬)和包含邏輯的類(如選擇第一個匹配項)。在你的邏輯類的構造函數中傳遞模擬庫,並測試它聲明預期的行爲。

+1

感謝您的指導,我沒有在一些小東西的旁邊使用模擬遊戲,我明白你的意思。我對嘲笑回購並不滿意,但我希望它能夠測試,並且讓我感覺不那麼有意義,因爲我剛開始着眼於測試服務層。我只是將模擬注入服務測試,這更有意義,我更習慣於。謝謝。 – BryanGrimes 2012-01-11 21:29:33