0

I need to unit-test a virtual method defined in an abstract class. But the base class is abstract, so I can't create an instance of it. What do you recommend me to do?

This is a follow up to the following question: I am thinking about if it is possible to test via an instance of a subclass of the abstract class. Is it a good way? How can I do it?

Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
Tim
  • 1
  • 141
  • 372
  • 590

2 Answers2

4

I'm not sure what your abstract class looks like, but if you have something like:

public abstract class SomeClass
{
    public abstract bool SomeMethod();

    public abstract int SomeOtherMethod();

    public virtual int MethodYouWantToTest()
    {
        // Method body
    }
}

And then, as @David suggested in the comments:

public class Test : SomeClass
{
    // You don't care about this method - this is just there to make it compile
    public override bool SomeMethod()
    {
        throw new NotImplementedException();
    }

    // You don't care about this method either
    public override int SomeOtherMethod()
    {
        throw new NotImplementedException();
    }

    // Do nothing to MethodYouWantToTest
}

Then you just instantiate Test for your unit test:

[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void TestMethod1()
    {
        SomeClass test = new Test();
        // Insert whatever value you expect here
        Assert.AreEqual(10, test.MethodYouWantToTest());
    }
}
  • Thanks. Where is `MethodYouWantToTest` called in teh test class? – Tim Jun 06 '17 at 23:09
  • @Tim I included an example of that - you can just instantiate `Test` and use it like you were using the abstract class (which is why you don't want to override `MethodYouWantToTest` in the `Test` class - that way you know that you're running the code from the base class). – EJoshuaS - Stand with Ukraine Jun 06 '17 at 23:16
4

There's no rule that says a unit test can't define its own classes. This is a fairly common practice (at least for me anyway).

Consider the structure of a standard unit test:

public void TestMethod()
{
    // arrange
    // act
    // assert
}

That "arrange" step can include any reasonable actions (without side-effects outside of the test) which set up what you're trying to test. This can just as easily include creating an instance of a class whose sole purpose is to run the test. For example, something like this:

private class TestSubClass : YourAbstractBase { }

public void TestMethod()
{
    // arrange
    var testObj = new TestSubClass();

    // act
    var result = testObj.YourVirtualMethod();

    // assert
    Assert.AreEqual(123, result);
}
David
  • 208,112
  • 36
  • 198
  • 279