繁体   English   中英

C#单元测试(Xunit和Moq)-分别测试接口及其实现

[英]C# Unit Testing (Xunit and Moq) - Test an interface and its implementations separately

我想将单元测试分开,以测试接口行为本身和实现的其他业务行为。

public interface IIncrementor
{
    void Increment();

    int Count { get; }
}

public class AIncrementor : IIncrementor { /* Implementation */ }
public class BIncrementor : IIncrementor { /* Implementation */ }

为了确保接口业务行为的正确性,我需要根据定义的单元测试检查所有相应的实现。 当然,每个实现都有自己的额外行为要测试,但是我不想一遍又一遍地重复自己。

我当前的解决方案是创建一个具有抽象属性的抽象测试类,以实现子类。

public abstract class IIncrementorTest
{
    protected abstract IIncrementor Incrementor { get; }

    [Fact]
    public void WhenIncremented_ThenCounterHasCorrectValue()
    {
        var oldCount = Incrementor.Count;

        Incrementor.Increment();

        Assert.Equal(oldCount + 1, Incrementor.Count);
    }
}

public class AIncremetorTest : IIncrementorTest
{
    protected override IIncrementor Incrementor => new AIncrementor();

    [Fact]
    public void WhenSomeAdditional_ThenCheckSomething() { /* More test */ }
}

public class BIncremetorTest : IIncrementorTest
{
    protected override IIncrementor Incrementor => new BIncrementor();

    [Fact]
    public void WhenSomeAdditional_ThenCheckSomething() { /* More test */ }
}

但这会带来一些问题,例如,当测试用例需要以不同的方式构建实例时,这很有可能会发生。 您是否建议为这些情况创建抽象属性?

protected abstract IIncrementor IncrementorForCheckingSomething { get; }

还是有一种最佳实践方法可以全面解决此接口测试问题?

如果我理解正确,则需要为接口编写一组测试,并将这些测试应用于实现该接口的任何类。

您可以使用反射来在程序集中找到使用以下方式实现接口的所有类型:

var interfaceType = typeof(IIncrementor);
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(a => a.GetTypes())
.Where(t => t.IsClass && interfaceType.IsAssignableFrom(t));

并实例化所有这些类型。 如果他们不共享通用的构造函数签名,这可能会很棘手。 但是可以使用默认构造函数处理问题中的示例...

foreach(Type t in types)
{
    yield return (IIncrementor)Activator.CreateInstance(t,null);
}

将该代码放入返回类型为IEnumerable<IIncrementor>方法中,并为该方法赋予MemberData属性,以将这些实例传递到每个测试中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM