简体   繁体   English

在 MSTest 中使用 inheritance 进行共享测试

[英]Use inheritance in MSTest for shared tests

I'm trying to write Unittests for D365 Plugins and CodeActivities (both being classes).我正在尝试为 D365 插件和 CodeActivities(都是类)编写单元测试。 There are small tests that should run in every plugin, such as:每个插件都应该运行一些小测试,例如:

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

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

Where SomePlugin is the class to be tested (which is for each child different) and cannot be abstract (awaits IPlugin ).其中SomePlugin是要测试的 class (每个孩子都不同)并且不能是抽象的(等待IPlugin )。 For example here it's a CheckDuplicateOrder in the child:例如,这里是孩子的CheckDuplicateOrder

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

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

For these small tests I'd like to have this parent with Shared tests but I don't know how to reference the 'to-be' child's target.对于这些小测试,我想让这个父母使用共享测试,但我不知道如何引用“未来”孩子的目标。 I prefer MSTest, but any NuGet framework is accepted.我更喜欢 MSTest,但任何 NuGet 框架都可以接受。

Maybe this helps with understanding也许这有助于理解

Every plugin would have it's own test class.每个插件都有自己的测试 class。 Every plugintest class needs the basic.每个插件测试 class 都需要基础。 These basic tests should be inherited from parent (so they don't take up space).这些基本测试应该从父级继承(所以它们不占用空间)。

Plugins: Dog, Cat, Mouse PluginTests: DogTest, CatTest, MouseTest BasePluginTest -> should have shared tests where SomePlugin in the exmaple is Dog/Cat/Mouse.插件:Dog、Cat、Mouse PluginTests:DogTest、CatTest、MouseTest BasePluginTest -> 应该有共享测试,其中示例中的SomePlugin是 Dog/Cat/Mouse。 But I don't know how to reference it.但我不知道如何引用它。 Every plugin would have a function TestWalk() {.. ExecutePluginWith<SomePlugin>} .每个插件都会有一个 function TestWalk() {.. ExecutePluginWith<SomePlugin>} The Cat should call CatTest, the Dog should call DogTest. Cat 应该调用 CatTest,Dog 应该调用 DogTest。

As with a normal class you should favour composition over inheritance.与普通的 class 一样,您应该更喜欢组合而不是 inheritance。 Even though test-classes do not have to follow the same rules and guidelines as normal classes doesn't mean we cannot implement them.即使测试类不必遵循与普通类相同的规则和准则,但这并不意味着我们不能实现它们。

So when you feel you have some common functionality accross your test-classes you should extract some class that is used by your tests.因此,当您觉得您的测试类中有一些通用功能时,您应该提取一些测试使用的 class。 You would do the same for a normal business-class also, won´t you?对于普通的商务舱,您也会这样做,不是吗?

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));
    }
}

You could also make your common method rethrow the exception instead of just returning true or false if you want to log the actual exception being thrown within the test-framework.如果您想记录在测试框架中抛出的实际异常,您还可以让您的常用方法重新抛出异常,而不是只返回truefalse

Disclaimer: some people won't like this because it abuses class inheritance to save code.免责声明:有些人不会喜欢这个,因为它滥用 class inheritance 来保存代码。 It's a potential tool for the job, you can evaluate whether it works for you or not.它是这项工作的潜在工具,您可以评估它是否适合您。

This seems like it could be achievable with a base class to define the shared tests.这似乎可以通过基础 class 来定义共享测试来实现。 Maybe something like this would achieve what you're trying to do?也许这样的事情会实现你想要做的事情?

// 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));
    }
}

Your plugin classes would inherit from this class:您的插件类将从这个 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
}

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

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