如何为MSpec的所有接口实现编写通用测试?

Dan*_*rth 8 c# bdd unit-testing mspec

我有IAudioProcessor一个单一方法的接口IEnumerable<Sample> Process(IEnumerable<Sample> samples).虽然它不是接口本身的要求,但我想确保我的所有实现遵循一些通用规则,例如:

  1. 使用延迟执行
  2. 请勿更改输入样本

为这些创建测试并不难,但我必须为每个实现复制并粘贴这些测试.我想避免这种情况.

我想做这样的事情(注意属性GenericTest和类型参数):

[GenericTest(typeof(AudioProcessorImpl1Factory))]
[GenericTest(typeof(AudioProcessorImpl2Factory))]
[GenericTest(typeof(AudioProcessorImpl3Factory))]
public class when_processed_audio_is_returned<TSutFactory>
    where TSutFactory : ISutFactory<IAudioProcessor>, new()
{
    static IAudioProcessor Sut = new TSutFactory().CreateSut();
    protected static Context _ = new Context();

    Establish context = () => _.Original = Substitute.For<IEnumerable<ISample>>();

    Because of = () => Sut.Process(_.Original);

    It should_not_have_enumerated_the_original_samples = () =>
    {
        _.Original.DidNotReceive().GetEnumerator();
        ((IEnumerable)_.Original).DidNotReceive().GetEnumerator();
    };
}
Run Code Online (Sandbox Code Playgroud)

这样的事情可能吗?

Ale*_*ffe 0

我为您 Binged MSpec 参数化测试:) http://groups.google.com/group/machine_users/browse_thread/thread/8419cde3f07ffcf2?pli=1

虽然它不会显示为单独的绿色/红色测试,但我认为没有什么可以阻止您从单个规范中枚举一系列工厂并断言每个实现的行为。这意味着即使一个实现失败,你的测试也会失败,但如果你想要参数化,你可以尝试像 NUnit 这样更宽松的测试套件。

编辑 1:我不确定 MSpec 是否支持发现继承字段来确定规范,但如果是这样,下面的代码至少应该最大限度地减少“重复”代码的数量,而无法使用属性:

private class base_when_processed_audio_is_returned<TSutFactory>
    where TSutFactory : ISutFactory<IAudioProcessor>, new()
{
    static IAudioProcessor Sut = new TSutFactory().CreateSut();
    protected static Context _ = new Context();

    Establish context = () => _.Original = Substitute.For<IEnumerable<ISample>>();

    public Because of = () => Sut.Process(_.Original);

    public It should_not_have_enumerated_the_original_samples = () =>
    {
        _.Original.DidNotReceive().GetEnumerator();
        ((IEnumerable)_.Original).DidNotReceive().GetEnumerator();
    };
}

public class when_processed_audio_is_returned_from_AudioProcessorImpl1Factory()
  : base_when_processed_audio_is_returned<AudioProcessorImpl1Factory>
{}

public class when_processed_audio_is_returned_from_AudioProcessorImpl2Factory()
  : base_when_processed_audio_is_returned<AudioProcessorImpl2Factory>
{}
Run Code Online (Sandbox Code Playgroud)