【问题标题】:Unit tests - refactor to share data between tests in C#单元测试 - 重构以在 C# 中的测试之间共享数据
【发布时间】:2014-11-20 10:29:14
【问题描述】:

我目前正在尝试重构一些单元测试,因为它们包含太多的硬编码数据。 类结构如下:

public class BaseClassValidator {
   [Test]
   public void TestAddress(){
     Address a = GetAddress();
     if (a != null){
        // verify and validate here
        Assert.AreEqual(..., ...);
     }
   }

   [Test]
   public void TestPhone(){
       // almost the same as above, with GetPhone();
   }

   // ... other public methods here ...

   protected Address GetAddress(){
     return null;
   }

   protected Phone GetPhone(){
     return null;
   }
}

public class US: BaseClassValidator{
    protected override Address GetAddress(){
       Address address = new Address();
       address.FirstName = "firstname";
       // fill in the address data ...
       return address;           
    }

    // override GetPhone as well and other protected methods
}

以及许多其他用于相同目的的类 - 验证国家/地区地址是否有效。 每个子类都必须重写获取测试数据的方法,正如您可以想象的那样,这使得文件越来越大,输入数据在我看来可以以不同的方式获取/设置。此外,其中一些子类定义了特定的测试成员来检查地址是否有效,有几个检查,例如:

public class US: BaseClassValidator {

    // override the method GetAddress, as explained above ...

    // define a new test method here...
    [Test]
    public void TestValidator {
        Address a = GetAddress();
        a.State = "KS";
        // validate the address
        // and assert that we get an error because state is wrong

        Address a = GetAddress();
        a.street = "";
        // validate and assert that we get an error because street is wrong


        // and so on...
    }

}

我想知道是否有更好的方法来做到这一点,因为我们似乎在部分使用基类来测试一些数据,但对于更具体的事情,我们正在使用子类 - 这可能是有道理的,但是那么似乎我们失去了使用上述模板模式的好处。我不喜欢创建数据的方式,因为使用不同的方法,例如使用数据驱动测试,我们可以从文件(例如 xml)中读取测试数据。

有没有更好的方法在测试之间共享数据? 遇到这种情况怎么处理?

【问题讨论】:

    标签: c# unit-testing nunit xunit data-driven-tests


    【解决方案1】:

    我想知道是否有更好的方法来做到这一点,因为看起来 我们部分地使用基类来测试一些数据,但是对于 我们正在使用子类更具体的东西——它可以使 有道理,但似乎我们失去了使用模板的好处 类似上面的模式。

    人们倾向于使用Composition over inheritance,这就是为什么使用子类不是单元测试的最佳解决方案。

    您尝试过Object MotherTest Data Builder 模式吗?它们可用于轻松构建测试数据。

    Test Data Builder用法的例子

    var defaultAddres = new AddressBuilder().Build();
    var addresWithState = new AddressBuilder().WithState("MyState").Build();
    var addresWithStreet2 = new AddressBuilder().WithStreet2("street 2 value").Build();
    

    及其简单的实现

    public class AddressBuilder
    {
        string state = "default STATE";
        string street1 = "default street 1";
        string street2 = "";
    
        public Address Build()
        {
            return new Address
            {
                State = state,
                Street1 = street1,
                Street2 = street2
            };
        }
    
        public AddressBuilder WithState(string value)
        {
            state = value;
            return this;
        }
    
        public AddressBuilder WithStreet1(string value)
        {
            street1 = value;
            return this;
        }
    
        public AddressBuilder WithStreet2(string value)
        {
            street2 = value;
            return this;
        }
    }
    

    【讨论】:

      【解决方案2】:

      我目前正在做类似的事情,并在我的项目中引入了 Data 类。这只是包含一堆静态数据。这是一个部分类,所以我可以稍微构造一下。我有一个DataOrder.cs、DataOrderLine.cs 等等。然后是公共属性,例如Orders,我可以在我的测试中使用它来获取我的测试数据。

      不要将所有数据都放在基类中,这样会更难维护。

      【讨论】:

      • 在特定情况下你会怎么做,比如“我需要一个地址,但我只需要更改一个字段,例如街道”?
      • 如果您需要特定数据,您仍然可以在测试中构建它。如果多个测试需要它,请将其移至 Data 类。
      猜你喜欢
      • 1970-01-01
      • 2022-10-04
      • 2018-12-21
      • 1970-01-01
      • 1970-01-01
      • 2023-03-09
      • 1970-01-01
      • 1970-01-01
      • 2017-10-15
      相关资源
      最近更新 更多