2015-11-10 13 views
5

Ben moq, ef 6 ve xunit kullanıyorum. Kendimi bu kodu tekrar tekrar yazmayı buldum ve belki de genel bir yönteme dönüştürmeyi başarabileceğimi düşündüm. Ben, bu verilerin bir listede alıp harika olurdu aracılığıyla bu yüzden sorguyu taklit kurmak istiyorsunuz bir yöntem yazabilirsiniz eğer öyleyse Bu EF Mock kurulum kodunu, yeniden kullanılabilir bir Generic Boilerplate olarak nasıl yazabilirim?

public static void CreateSalesMock(List<Sale> sales, Mock<DatabaseContext> dbContextMock) 
{ 
    var data = sales.AsQueryable(); 

    var mockSet = new Mock<DbSet<Sale>>(); 
    mockSet.As<IQueryable<Sale>>() 
      .Setup(x => x.Provider) 
      .Returns(data.Provider); 
    mockSet.As<IQueryable<Sale>>() 
      .Setup(x => x.Expression) 
      .Returns(data.Expression); 
    mockSet.As<IQueryable<Sale>>() 
      .Setup(x => x.ElementType) 
      .Returns(data.ElementType); 
    mockSet.As<IQueryable<Sale>>() 
      .Setup(x => x.GetEnumerator()) 
      .Returns(data.GetEnumerator()); 

    dbContextMock.Setup(x => x.Sales).Returns(mockSet.Object); 
} 

Şimdi benim veritabanında birçok tablolar var.

public static void CreateMockSet<T, TA, TB>(T dataList, TA model, 
    Func<TB> lambda, Mock<DatabaseContext> dbContextMock) 
    where T : List<T> 
    where TA: Mock<DbSet<TA>> 
{ 
    var data = dataList.AsQueryable(); 

    model.As<IQueryable<T>>() 
     .Setup(x => x.Provider) 
     .Returns(data.Provider); 
    model.As<IQueryable<T>>() 
     .Setup(x => x.Expression) 
     .Returns(data.Expression); 
    model.As<IQueryable<T>>() 
     .Setup(x => x.ElementType) 
     .Returns(data.ElementType); 
    model.As<IQueryable<T>>() 
     .Setup(x => x.GetEnumerator()) 
     .Returns(data.GetEnumerator()); 

    dbContextMock.Setup(x => lambda); 
} 

Şimdiye kadar var ama işe yarayıp yaramayacağından emin değilim. Ben "lambda" bölümünde (örneğin, x => x.Sales) geçerken sıkışıp kaldım, bu yüzden test bile edemiyorum.

var context = new Mock<DatabaseContext>(); 
context.setup(x => x.Sales).ReturnsDbSet(new List<Sale>(){put here the items..}); 

Edit

: Aşağıdaki gibi kullanabilirsiniz UT Sonra

public static class DbSetMocking 
{ 
    private static Mock<DbSet<T>> CreateMockSet<T>(IQueryable<T> data) 
      where T : class 
    { 
     var queryableData = data.AsQueryable(); 
     var mockSet = new Mock<DbSet<T>>(); 
     mockSet.As<IQueryable<T>>().Setup(m => m.Provider) 
       .Returns(queryableData.Provider); 
     mockSet.As<IQueryable<T>>().Setup(m => m.Expression) 
       .Returns(queryableData.Expression); 
     mockSet.As<IQueryable<T>>().Setup(m => m.ElementType) 
       .Returns(queryableData.ElementType); 
     mockSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()) 
       .Returns(queryableData.GetEnumerator()); 
     return mockSet; 
    } 

    public static IReturnsResult<TContext> ReturnsDbSet<TEntity, TContext>(
      this IReturns<TContext, DbSet<TEntity>> setup, 
      TEntity[] entities) 
     where TEntity : class 
     where TContext : DbContext 
    { 
     Mock<DbSet<TEntity>> mockSet; 
     return ReturnsDbSet(setup, entities, out mockSet); 
    } 

    public static IReturnsResult<TContext> ReturnsDbSet<TEntity, TContext>(
      this IReturns<TContext, DbSet<TEntity>> setup, 
      IQueryable<TEntity> entities) 
     where TEntity : class 
     where TContext : DbContext 
    { 

     Mock<DbSet<TEntity>> mockSet; 
     return ReturnsDbSet(setup, entities, out mockSet); 
    } 

    public static IReturnsResult<TContext> ReturnsDbSet<TEntity, TContext>(
      this IReturns<TContext, DbSet<TEntity>> setup, 
      IEnumerable<TEntity> entities) 
     where TEntity : class 
     where TContext : DbContext 
    { 
     Mock<DbSet<TEntity>> mockSet; 
     return ReturnsDbSet(setup, entities, out mockSet); 
    } 

    public static IReturnsResult<TContext> ReturnsDbSet<TEntity, TContext>(
    this IReturns<TContext, DbSet<TEntity>> setup, 
    TEntity[] entities, out Mock<DbSet<TEntity>> mockSet) 
     where TEntity : class 
     where TContext : DbContext 
    { 
     mockSet = CreateMockSet(entities.AsQueryable()); 
     return setup.Returns(mockSet.Object); 
    } 

    public static IReturnsResult<TContext> ReturnsDbSet<TEntity, TContext>(
      this IReturns<TContext, DbSet<TEntity>> setup, 
      IQueryable<TEntity> entities, out Mock<DbSet<TEntity>> mockSet) 
     where TEntity : class 
     where TContext : DbContext 
    { 

     mockSet = CreateMockSet(entities); 
     return setup.Returns(mockSet.Object); 
    } 

    public static IReturnsResult<TContext> ReturnsDbSet<TEntity, TContext>(
    this IReturns<TContext, DbSet<TEntity>> setup, 
    IEnumerable<TEntity> entities, out Mock<DbSet<TEntity>> mockSet) 
     where TEntity : class 
     where TContext : DbContext 
    { 
     mockSet = CreateMockSet(entities.AsQueryable()); 
     return setup.Returns(mockSet.Object); 
    } 

} 

:

+0

Ben değiştirmek istediğiniz düşünüyorum 'kısıt bir arabirim tanıtmak where': Şimdi DbSet<T> mülkiyet doğrulama olanağı 3 daha fazla yüklenmeleri vardır' burada T: Liste '. –

+0

Builder Kalıbına bir göz atmanızı tavsiye ederim https://www.kenneth-truyers.net/2013/07/15/flexible-and-expressive-unit-tests-with-the-builder-pattern/ –

+0

@ ToddSprang IBase'nin ne olacağından emin değilim. Daha fazla örnek verebilir misiniz – chobo2

cevap

9

Tim Larson zaten his blog bu klişe kodu için mükemmel bir çözüm sundu Kodu güncelledim.

[TestMethod] 
    public void TestMethod1() 
    { 
     var sales = new List<Sale> 
     { 
      new Sale() {id = 1}, 
      new Sale() {id = 6}, 
      new Sale() {id = 5}, 
      new Sale() {id = 4}, 
      new Sale() {id = 3}, 
      new Sale() {id = 2} 
     }; 
     var fakeContest = new Mock<SalesContext>(); 
     Mock<DbSet<Sale>> fakeSet; 
     fakeContest.Setup(context => context.Sales).ReturnsDbSet(sales, out fakeSet); 

     var itemsToRemove = sales.Where(sale => sale.id%2 == 0); 


     fakeContest.Object.Sales.RemoveRange(itemsToRemove); 


     fakeSet.Verify(set => set.RemoveRange(itemsToRemove)); 

    } 
+0

Cool, aradığım şey bu, ama Mockset'e daha fazla Kurulum eklemem gerekirse ne olur? Örneğin, sadece SalesMock üzerinde doğrulamayı çalıştırdığımdan ve çalışmamdan önce RemoveRange'ın çağrıldığını görmek istiyorum. ama şimdi sahip değilim, ne yapacağımı bilmiyorum. Doğrulamayı dbContext.Verify (x => x.Sales.RemoveRange (...)) aracılığıyla yapmaya çalıştım ancak bu her zaman başarısız oluyor. – chobo2

+0

@ chobo2 Böyle bir şey yapma. context.Sales, BCL koleksiyonu olan "Satış" ın bir listesidir. BCL koleksiyonlarına uymamalısınız. Bunu yapmak yerine, listenin artık öğeleri içermediğini doğrulayın. –

+0

Listeyi artık öğeler içermediğini nasıl sınarım? İlk önce denedim ama birim test tarafım hiç çıkarılmadı. Hizmetimde olduğu gibi onları kaldırıldığını gördüm ama orijinal koleksiyonuma baktığımda hepsi orada hala oradalar. – chobo2

İlgili konular