使用不同的数据模型进行测试

时间:2011-11-08 04:19:59

标签: c# .net unit-testing model nunit

我的许多班级单元测试加载数据模型并执行各种类级别测试。但是,许多业务逻辑依赖于模型中的数据。因此我的班级测试看起来像这样:

 public class TestFoo
 {
     // Data model
     Model _myDataModel; 

     // Class under test
     Foo _foo;

     [Setup] 
     public void Initialize()
     {
         // Create data model
         _myDataModel = new Model();
         _myDataModel.Load();   // Loads the file

         // Create the class under test
         _foo = new Foo();
     }

     [TearDown]
     public void Dispose()
     {
     }

     [Test]
     public void TestFooCase1()
     {
         // Code for test case that tests _foo and uses the data model  
     }
 } 

但是,我想用两个或更多数据模型运行我的大部分测试,即我需要在设置方法中调用_myDataModel.LoadModelX()_myDataModel.LoadModelY()

我想到的一种方法是通过在测试用例本身中实例化模型,如下所示,但这需要在每个测试用例中调用load方法。

[Setup] 
public void Initialize()
{       
    // Create the class under test
    _foo = new Foo();
}

[TearDown]
public void Dispose()
{
}

// Use TestCase to specify the model as an argument for each test case  
[TestCase(modelX)]
[TestCase(modelY)]
public void TestFooCase1(string modelName)
{
    // Create data model
    _myDataModel = new Model();
    _myDataModel.Load(modelName);   // New method which loads the specific model 

    // Code for test case that tests _foo and uses the data model       
}   

我认为必须有一个更好的方法可能是通过定义我自己的属性或扩展NUnitTestFixture。我对其他想法感兴趣。

4 个答案:

答案 0 :(得分:1)

您可以为要测试的每个模型组合设置属性,然后使用ValueSource attribute传递准备加载的模型。像这样的东西

private static IEnumerable<Model> ModelsToTest
{
  get
  {
    Model x = new Model();
    x.Load("X");
    yield return x;

    Model y = new Model();
    y.Load("Y");
    yield return y;
  }
}

[Test]
public void TestFooCase1([ValueSource("ModelsToTest")] Model model)
{
  // Code for test case that tests _foo and uses the data model       
} 

答案 1 :(得分:0)

  

许多业务逻辑取决于模型中的数据

考虑到我建议为每个模型特定情况创建单独的测试,并且不要将不同的modelx混合到单个测试夹具中。

BTW,将Dispose()方法重命名为TearDown(),因为Dispose直观地与Dispose模式实现相关联(IDisposable)所以这搞砸了因为你只做了明确的NUnitЕearDown阶段按属性[TearDown]。

答案 2 :(得分:0)

我不喜欢设置和拆卸,因为我想要测试方法中存在的信息。因此,我更喜欢在测试中创建所有testdata,并且我发现ESSENTIAL在测试方法中创建了测试对象。

我喜欢的是用于创建testdata的构建器模式。

public class DataModelBuilder
{  
  string _modelName; 
  IDataModel _dataModel; 

  public DataModelBuilder WithModelName(string modelName)
  {
    _modelName = modelName; 
    return this; 
  }

  public IDataModel Build()
  {
    _dataModel = new DataModel(); 
    _datamodel.Load(_modelName); 
    return _dataModel; 
  }

}

在测试方法中,创建模型的语法为:

IDataModel _model = new DataModelBuilder().WithNewName("modelY").Build(); 

复杂测试数据的简洁明了的单行创建,有助于在测试用例中显示与测试用例相关的所有信息。我不希望在设置方法中隐藏这些信息。

请注意,构建器与模拟相结合会变得更加强大。

答案 3 :(得分:-1)

我不喜欢[Setup][TearDown]这样宣布下一个类的属性:

class DisposableList : List<IDisposable>, IDisposable
{
    public Dipose()
    {
        foreach (var x in this) x.Dispose();
    }
}

并使用它:

[Test...]
public void MyTest()
{
    using (NewContext(...))
    {
        // perform test here
    }
}

private static NewContext(...)
{
    var list = new DisposableList();

    // add anything here

    return list;
}

优点:

  • 您可以在单个测试或类中多次初始化测试状态(调用NewContext()
  • 您可以使用不同的值初始化测试状态,例如NewContext((x) => x.LoadY())