XUnit-使用扩展方法将可重用测试助手放置在外部共享类库中的设计架构

时间:2018-08-24 11:05:15

标签: c# unit-testing xunit

为大量业务对象类(超过400个)设计一些XUnit测试。将会有很多重复的代码,因此采用DRY原理,我们有很多选择,可以将代码抽象和封装到共享的类库中。

  1. 传统静态助手类。一种用于进行常规测试的方法,用于传入实例的参数和任何设置。
  2. 业务类上的
  3. 扩展方法。如上所述,但作为业务类/接口类型本身的扩展方法。

将测试创建为扩展方法(选项2),是否违反了单元测试的原则,即提示仅测试较小的特定单元。现在,小型测试链可以分组为父级测试吗?

是否还有其他设计体系结构模式可以使共享库重用于域实体的通用测试?

下面的代码演示了这两个选项。请注意,Helper类将位于与UnitTest类(Test_Person)项目分开的另一个Class Lib项目中。

using Xunit;
namespace CCTools.UnitTest.Main.XUnit.UnitTestPatterns
{

public class Test_Person
{
    /// <summary>
    ///     Use Extension methods, quick to code and easy to read.
    /// </summary>
    [Fact]
    public static void Test_Stuff_UseExtenions_A()
    {
        Person p = new Person();
        //Do lots of other config and tests...
        p.Test_IncreaseCreditRating(187);
        p.IsManager = true;
        p.Test_CreditRating_is_valid_for_manager();
    }

    [Fact]
    public static void Test_Stuff_UseExtenions_B()
    {
        Person p = new Person();
        //Do lots of other config and tests...

        p.Test_IncreaseCreditRating(59);
        p.Test_CreditRating_is_valid_for_manager();
    }

    /// <summary>
    ///     Use traditional Helper methods, not as easy to read or code.
    /// </summary>
    [Fact]
    public static void Test_Stuff_UseHelper_A()
    {
        Person p = new Person();
        //Do lots of other config and tests...

        PersonUniTestHelper.Test_IncreaseCreditRating(p, 10);
        p.IsManager = true;
        PersonUniTestHelper.Test_CreditRating_is_valid_for_manager(p);
    }
}
/// <summary>
///     Extension methods, which makes coding far easier on the eye and one is able to locate all methods
///     using intellisense at a glance.
/// </summary>
public static class PersonUniTestExtensionMethods
{
    public static void Test_IncreaseCreditRating(this Person person, int creditRating)
    {
        person.IncreaseCreditRating(creditRating);
        if (creditRating >= 100) Assert.Equal(100 * 1000, person.CreditLimit);
        else Assert.Equal(creditRating * 1000, person.CreditLimit);
    }

    public static void Test_CreditRating_is_valid_for_manager(this Person person)
    {
        if (person.IsManager) Assert.True(person.CreditRating >= 50);
    }
}

/// <summary>
///     Traditional static class for helpers
/// </summary>
public static class PersonUniTestHelper
{
    public static void Test_IncreaseCreditRating(Person person, int creditRating)
    {
        person.IncreaseCreditRating(creditRating);
        if (creditRating >= 100) Assert.Equal(100 * 1000, person.CreditLimit);
        else Assert.Equal(creditRating * 1000, person.CreditLimit);
    }

    public static void Test_CreditRating_is_valid_for_manager(Person person)
    {
        if (person.IsManager) Assert.True(person.CreditRating >= 50);
    }
}


public class Person
{
    public string FirstName { get; set; }
    public int CreditLimit { get; private set; }
    public int CreditRating { get; private set; }

    public bool IsManager { get; set; }

    /// <summary>
    ///     Simple action to set CreditLimit based on Rating.
    /// </summary>
    public void IncreaseCreditRating(int creditRating)
    {
        CreditRating = creditRating;
        CreditLimit = creditRating >= 100 ? 100 * 1000 : creditRating * 1000;
    }
}
}

0 个答案:

没有答案