2017-08-04 68 views
1

我是TDD开发新手,刚刚开始做一些测试,包括Nunit 3.7.1,Newtonsoft.Json版本= 10.0.3,JustMock Lite版本2016.2.426.1,C#和.NET Framework 4.7。如何模拟一个IGenericRepository

我想测试这个类:

public class LoadFinishedTrzlBatch 
{ 
    private IGenericRepository<ProductionOrder> proOrdRepository; 
    private IGenericRepository<Batch> batchRepository; 
    private IGenericRepository<Code> codeRepository; 
    private IGenericRepository<Aggregation> aggregationRepository; 
    private IGenericRepository<AggregationChildren> aggChildrenRepository; 

    public LoadFinishedTrzlBatch(
     IGenericRepository<ProductionOrder> proOrdRepository, 
     IGenericRepository<Batch> batchRepository, 
     IGenericRepository<Code> codeRepository, 
     IGenericRepository<Aggregation> aggregationRepository, 
     IGenericRepository<AggregationChildren> aggChildrenRepository) 
    { 
     this.proOrdRepository = proOrdRepository; 
     this.batchRepository = batchRepository; 
     this.codeRepository = codeRepository; 
     this.aggregationRepository = aggregationRepository; 
     this.aggChildrenRepository = aggChildrenRepository; 
    } 

    public bool ExistsProductionOrder(string productionOrderName) 
    { 
     if (string.IsNullOrWhiteSpace(productionOrderName)) 
      throw new ArgumentNullException(nameof(productionOrderName)); 

     return (
      proOrdRepository 
       .SearchFor(p => p.Name == productionOrderName) 
       .FirstOrDefault() != null 
     ); 
    } 
} 

有了这个测试:

[TestFixture] 
class LoadFinishedTrzlBatchTest 
{ 
    private LoadFinishedTrzlBatch _load; 

    [SetUp] 
    public void SetUpLoadFinishedTrzlBatch() 
    { 
     var proOrdRepository = 
      Mock.Create<IGenericRepository<ProductionOrder>>(); 
     var batchRepository = 
      Mock.Create<IGenericRepository<Batch>>(); 
     var codeRepository = 
      Mock.Create<IGenericRepository<Code>>(); 
     var aggRepository = 
      Mock.Create<IGenericRepository<Aggregation>>(); 
     var aggChildrenRepository = 
      Mock.Create<IGenericRepository<AggregationChildren>>(); 

     _load = new LoadFinishedTrzlBatch(
      proOrdRepository, 
      batchRepository, 
      codeRepository, 
      aggRepository, 
      aggChildrenRepository); 
    } 

    [Test] 
    public void ShouldExistsProductionOrder() 
    { 
     // Arrange 
     Mock.Arrange(() => _load.ExistsProductionOrder("ProOrd")) 
      .Returns(true) 
      .MustBeCalled(); 

     // Act 
     var actual = _load.ExistsProductionOrder("ProOrd"); 

     // Assert 
     Assert.AreEqual(actual, true); 
    } 
} 

最后这是IGenericRepository

public interface IGenericRepository<TEntity> 
{ 
    [ OMITTED ] 

    IQueryable<TEntity> SearchFor(Expression<Func<TEntity, bool>> predicate); 

    [ OMITTED ] 
} 

首先,我不知道如果这是测试方法LoadFinishedTrzlBatch.ExistsProductionOrder的正确方法。 TDD对我来说都是新事物,我迷失了方向。我很困惑我如何嘲笑IGenericRepository<ProductionOrder>。它总是如此,我不测试IGenericRepository<ProductionOrder>。也许是因为我没有测试版本库。

我在学习,我不知道我在做什么。这就是我问这个问题的原因。我想测试ExistsProductionOrder方法。

我该如何测试ExistsProductionOrder方法?

+1

这不是真的很清楚你实际上试图在这里测试。如果你正在测试'ExistsProductionOrder'方法,那么你为什么要嘲笑它呢? – DavidG

+0

因为我在学习,我不知道我在做什么。这就是我问这个问题的原因。我想测试'ExistsProductionOrder'方法。 – VansFannel

+0

然后,您应该以原始形式(即未嘲笑)调用它,并且只嘲笑依赖关系,特别是那些相关依赖关系的任何方法。 – DavidG

回答

1

您需要分离目标依赖关系,以便它可以在测试用例中隔离安排。你也不会模拟SUT(受试者)。你嘲笑它的依赖关系。在这种情况下,您想要模拟通用存储库并安排被调用的方法。即SearchFor

假设该方法采用表达谓词,您可以安排模拟期望一个,然后将其应用到假集合存储库以模拟实际的数据存储。

[TestFixture] 
public class LoadFinishedTrzlBatchTest { 
    private LoadFinishedTrzlBatch sut; 
    //need this later so declaring as field. 
    private IGenericRepository<ProductionOrder> proOrdRepository; 

    [SetUp] 
    public void SetUpLoadFinishedTrzlBatch() { 
     //Not using these so they can be declared locally   
     var batchRepository = 
      Mock.Create<IGenericRepository<Batch>>(); 
     var codeRepository = 
      Mock.Create<IGenericRepository<Code>>(); 
     var aggRepository = 
      Mock.Create<IGenericRepository<Aggregation>>(); 
     var aggChildrenRepository = 
      Mock.Create<IGenericRepository<AggregationChildren>>(); 

     //initializing target mock 
     proOrdRepository = 
      Mock.Create<IGenericRepository<ProductionOrder>>(); 

     sut = new LoadFinishedTrzlBatch(
      proOrdRepository, 
      batchRepository, 
      codeRepository, 
      aggRepository, 
      aggChildrenRepository); 
    } 

    [Test] 
    public void ShouldExistsProductionOrder() 
    { 
     // Arrange 
     var productionOrderName = "ProOrd"; 
     var orders = new List<ProductionOrder>() { 
      new ProductionOrder { Name = productionOrderName }, 
      new ProductionOrder { Name = "Dummy for Filter" } 
     }; 
     Mock.Arrange(() => proOrdRepository 
      .SearchFor(Arg.IsAny<Expression<Func<ProductionOrder,bool>>>())) 
      .Returns((Expression<Func<ProductionOrder,bool>> expression) => 
       orders.Where(expression.Compile()).AsQueryable() 
      ) 
      .MustBeCalled(); 

     // Act 
     var actual = sut.ExistsProductionOrder(productionOrderName); 

     // Assert 
     Assert.IsTrue(actual); 
    } 
} 
+0

对不起,我一直在假期,现在我已经测试了你的解决方案,但是当我创建proOrdRepository时,我得到了以下错误信息:'InvalidOperationException:NUnit.Framework.TestFixtureSetUpAttribute,nunit.framework,NUnit.Framework.TestFixtureTearDownAttribute ,未找到nunit.framework'。 – VansFannel

+0

我问过这个问题:https://stackoverflow.com/questions/45932110/typeinitializationexception-in-nunit-or-justmock – VansFannel

+0

@VansFannel将初始化代码移入设置函数。 – Nkosi

1

其实你想要测试如果方法ExistsProductionOrder做它应该做的。因此你不应该模拟它。但是,您希望嘲笑以内的方法,例如任何致电IGenericRepository<T>.DoSomething()的方法。

但只是把它和它的结果与你所期望的比较:

[Test] 
public void ShouldExistsProductionOrder() 
{ 
    // Act 
    var actual = _load.ExistsProductionOrder("ProOrd"); 
    Assert.IsTrue(actual); 
} 

现在,当你的方法是这样的:

bool ExistsProductionOrder() { 
    this.proOrdRepository.DoSomething(); 
    return ... 
} 

可以更换呼叫DoSomething的东西不同 - 你的模拟。