2015-11-10 6 views
5

मैं moq, ef 6 और xunit का उपयोग कर रहा हूँ। मैं खुद को इस कोड को बार-बार लिख रहा हूं और सोचा कि शायद मैं इसे एक सामान्य विधि में बना सकता हूं लेकिन कुछ परेशानी हो रही है।इस ईएफ मॉक सेटअप कोड को पुन: प्रयोज्य जेनेरिक बॉयलरप्लेट के रूप में कैसे लिखें?

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); 
} 

अब मैं तो अगर मैं एक विधि है कि है कि डेटा की एक सूची में लेने के लिए और इसे सेट अप तो मैं क्वेरी नकली कर सकते हैं के माध्यम से यह बहुत अच्छा होगा होगा लिख ​​सकता है मेरी डेटाबेस में कई अन्य तालिकाओं की है।

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); 
} 

अभी तक मेरे पास है लेकिन मुझे यकीन नहीं है कि यह काम करेगा या नहीं। मैं उदाहरण के लिए "लैम्ब्डा" भाग में गुजर रहा हूं (x => x.Sales) इसलिए मैं इसका परीक्षण भी नहीं कर सकता। केन्द्र शासित प्रदेशों में तो

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

मुझे लगता है कि आप बदलना चाहते हैं 'एक अंतरफलक शुरू करने की बाधा where':: अब वहाँ 3 अधिक भार के जो DbSet<T> संपत्ति पर सत्यापन की अनुमति देता है कर रहे हैं' जहां टी: सूची '। –

+0

मैं बिल्डर पैटर्न पर एक नज़र डालने की सिफारिश करता हूं https://www.kenneth-truyers.net/2013/07/15/flexible-and-expressive-unit-tests-with-the-builder-pattern/ –

+0

@ ToddSprang मुझे यकीन नहीं है कि आईबीएएस क्या होगा। क्या आप – chobo2

उत्तर

9

टिम लार्सन पहले से ही his blog में इस बॉयलरप्लेट कोड के लिए एक महान समाधान की पेशकश की

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

संपादित

मैंने कोड अपडेट किया।

[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

कूल का एक उदाहरण दे सकते हैं, यह वही है जो मैं ढूंढ रहा था लेकिन अगर मुझे मोक्ससेट में और सेटअप जोड़ने की ज़रूरत है तो क्या होगा? उदाहरण के लिए, मैं देखना चाहता हूं कि अगर RemoveMange पर सत्यापन समाप्त हो गया है और यह काम करता है तो इससे पहले कि RemoveRange को कॉल किया गया था। लेकिन अब मेरे पास यह नहीं है मुझे यकीन नहीं है कि क्या करना है। मैंने dbContext के माध्यम से सत्यापित करने की कोशिश की। सत्यापित करें (x => x.Sales.RemoveRange (...)) लेकिन यह हमेशा विफल रहता है। – chobo2

+0

@ chobo2 ऐसी कोई काम न करें। 'संदर्भ। सेल' 'बिक्री 'की' सूची 'है जो एक बीसीएल संग्रह है। आपको बीसीएल संग्रहों का नकल नहीं करना चाहिए। ऐसा करने के बजाय सत्यापित करें कि सूची में अब तत्व शामिल नहीं हैं। –

+0

मैं सूची का परीक्षण कैसे करूं जिसमें अब तत्व शामिल नहीं हैं? मैंने पहले कोशिश की लेकिन मेरी इकाई परीक्षण पक्ष कभी उन्हें हटा नहीं लग रहा था। मेरी सेवा की तरह मैंने उन्हें हटा दिया लेकिन जब मैंने अपने मूल संग्रह को देखा, जहां वे अभी भी वहां हैं। – chobo2

संबंधित मुद्दे