简体   繁体   中英

How to mock An Abstract Base Class

I have a base class called "Question" and several child classes such as "TrueFalse", "MultipleChoice", "MatchPairs" etc...

The base class has methods with logic that all of the child classes use, such as sending off scores and raising events.

I have set my unit tests up for the child classes but I am not sure how I can setup unit tests for the methods in the base class.

I did some searching and I understand I need to create a Mock of the class but I am not sure how to do this as I have only seen how to do this on an instantiable object.

I have Moq & NUnit installed in project so ideally id like to use this. I am still new to programming and this is my first time adding unit tests so I appreciate any advice you can give me.

I did a search on site first and found a couple of similar questions but they did not give any example on how to do it, just that it needed to be mocked.

Many thanks.

From this answer it looks like what you need is something along these lines:

[Test]
public void MoqTest()
{
    var mock = new Moq.Mock<AbstractBaseClass>();            
    // set the behavior of mocked methods
    mock.Setup(abs => abs.Foo()).Returns(5);

    // getting an instance of the class
    var abstractBaseClass = mock.Object;
    // Asseting it actually works :)
    Assert.AreEqual(5, abstractBaseClass.Foo());
}

I was trying to mock an abstract class and this way didn't worked for me. what did work was to create a new class that extended the abstract class

class newclass : abstractClass
{
}

like this I could set the property and test the main method

There is no simple way to test it,

The best option is:

  • mark base class methods as virtual
  • create test classes for each of the "TrueFalse", "MultipleChoice", "MatchPairs" classes with virtual methods overridden and invoke public Abstract method.

So for example you have next inheritance structure

class Question {
     protected virtual bool CheckCorrect(params int[] answers){
          return answers.Any(x => x== 42);
     }
}

class TrueFalse: Question {
     
     public int SelectedAnswer {get;set;}
     public bool IsCorrect(){
          return CheckCorrect(SelectedAnswer );
     }
}
class MultipleChoice: Question {
     public int[] SelectedAnswers {get;set;}
     public bool IsCorrect(){
          return CheckCorrect(SelectedAnswers );
     }
}

Test methods for this:

abstract class TrueFalseTest: TrueFalseTest{

     public abstract bool CheckCorrectReal(params int[] answers);
     
     public override bool CheckCorrect(params int[] answers){
          return CheckCorrect(SelectedAnswer );
     }
}

abstract  class MultipleChoiceTest: MultipleChoice {
     public abstract bool CheckCorrectReal(params int[] answers);
     
     public override bool CheckCorrect(params int[] answers){
          return CheckCorrect(SelectedAnswer );
     }
}

And test methods itself:

class TestQuestionForms{
    [Fact]
    public void TrueFalseTest_ShouldExecute_CheckCorrectReal()
    {
        //setup
        var mock = new Mock<TrueFalseTest>();

        mock.Setup(q => q.CheckCorrectReal(It.IsAny<int[] answers>))
            .Returns(true);

        //action
        mock.Object.IsCorrect();
       
       //assert
       mock.Verify(db => db.CheckCorrectReal());

    }
    [Fact]
    public void MultipleChoiceTest_ShouldExecute_CheckCorrectReal()
    {   
        //setup
        var mock = new Mock<MultipleChoiceTest>();

        mock.Setup(q => q.CheckCorrectReal(It.IsAny<int[] answers>))
            .Returns(true);

        //action
        mock.Object.IsCorrect();
       
       //assert
       mock.Verify(db => db.CheckCorrectReal());

    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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