Search code examples
c#unit-testingdynamics-crmmstest

Use inheritance in MSTest for shared tests


I'm trying to write Unittests for D365 Plugins and CodeActivities (both being classes). 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). For example here it's a CheckDuplicateOrder in the child:

[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.

Maybe this helps with understanding

Every plugin would have it's own test class. Every plugintest class needs the basic. 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. But I don't know how to reference it. Every plugin would have a function TestWalk() { .. ExecutePluginWith<SomePlugin>}. The Cat should call CatTest, the Dog should call DogTest.


Solution

  • Disclaimer: some people won't like this because it abuses class inheritance to save code. 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. 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:

    [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
    }