在 MSTest 中使用继承进行共享测试

Use inheritance in MSTest for shared tests

我正在尝试为 D365 插件和 CodeActivities(两者都是 classes)编写单元测试。每个插件里都有一些小测试应该运行,比如:

[TestMethod]
public void NullLocalPluginContext()
{
    XrmFakedContext context = new XrmFakedContext();

    Assert.ThrowsException<InvalidPluginExecutionException>(
        () => context.ExecutePluginWith<SomePlugin>(null));
}

其中SomePlugin是要测试的class(每个child不同),不能是抽象的(等待IPlugin)。例如这里是 child:

中的 CheckDuplicateOrder
[TestClass]
public class CheckDuplicateOrderTest
{
    [TestMethod]
    public void NullLocalPluginContext()
    {
        XrmFakedContext context = new XrmFakedContext();

        Assert.ThrowsException<Exception>(
            () => context.ExecutePluginWith<CheckDuplicateOrder>(null));
    }
}

对于这些小型测试,我希望 parent 具有共享测试,但我不知道如何引用 'to-be' child 的目标。 我更喜欢 MSTest,但任何 NuGet 框架都可以接受。

Maybe this helps with understanding

每个插件都有自己的测试class。 每个插件测试 class 都需要基本的。 这些基本测试应该继承自parent(所以它们不会占用space)。

插件:狗、猫、老鼠 插件测试:DogTest、CatTest、MouseTest BasePluginTest -> 应该有共享测试,其中示例中的 SomePlugin 是 Dog/Cat/Mouse。但我不知道如何引用它。每个插件都会有一个函数 TestWalk() { .. ExecutePluginWith<SomePlugin>}。 Cat 应该调用 CatTest,Dog 应该调用 DogTest。

免责声明:有些人不喜欢这个,因为它滥用 class 继承来保存代码。它是工作的潜在工具,您可以评估它是否适合您。

这似乎可以通过基础 class 来定义共享测试来实现。也许这样的事情会实现你想要做的事情?

// note: no [TestClass] on this type so it doesn't get discovered by MSTest.  
// Probably should also be abstract.
public class SharedTests<T> where T : IPlugin
{
    [TestMethod]
    public void NullLocalPluginContext()
    {
        XrmFakedContext context = new XrmFakedContext();

        Assert.ThrowsException<Exception>(
            () => context.ExecutePluginWith<T>(null));
    }
}

您的插件 classes 将继承自此 class:

[TestClass]
public class CheckDuplicateOrderTests : SharedTests<CheckDuplicateOrder>
{
    // NullLocalPluginContext test is inherited from the parent type
}

[TestClass]
public class SomeOtherPluginTests : SharedTests<SomeOtherPlugin>
{
    // Also has NullLocalPluginContext test inherited, but for testing SomeOtherPlugin
}

与正常的 class 一样,您应该更喜欢组合而不是继承。甚至 尽管测试classes 没有 遵循与正常classes 相同的规则和准则,但这并不意味着我们无法实施它们。

因此,当您觉得您的测试 class 中有一些通用功能时,您应该提取一些测试使用的 class。对于正常的业务,您也会这样做-class,不是吗?

class CommonFunc 
{ 
    public static bool NullLocalPluginContext<T, TException>() where T: IPlugIn, TException : Exception
    {
        XrmFakedContext context = new XrmFakedContext();
        try { context.ExecutePluginWith<T>(null)) };
        catch (T e) { return true; }
        return false;
    }
}

[TestClass]
public class CheckDuplicateOrderTests
{
    [TestMethod]
    public void NullLocalPluginContext()
    {
        Assert.IsTrue(CommonFunc.NullLocalPluginContext<CheckDuplicateOrder, Exception>(null));
    }
}

[TestClass]
public class SomeOtherPluginTests
{
    [TestMethod]
    public void NullLocalPluginContext()
    {
        Assert.IsTrue(CommonFunc.NullLocalPluginContext<SomePlugin, InvalidPluginExecutionException>(null));
    }
}

如果您想记录在测试框架中抛出的实际异常,您也可以让您的通用方法重新抛出异常,而不仅仅是返回 truefalse