6

I want to write unit tests for MyClass but its base class is an abstract class.

public class MyClass : AbstractBaseClass
{
}

I want to Mock the AbstractBase class, so that I can skip some of the logic in its constructor when I create the MyClass instance I want to test. Is there anyway I can do this?

//Unit Test
var test = new Mock<IInterface>();
var derivedclass = new DerivedClass(test.Object);

test.Setup(d=>d.MyMethod(It.IsAny<string>()).returns(2);
derivedclass.MyMethod("hello");


// Derived Class
class DerivedClass : AbstractClass{

     //constuctor
    public DerivedClass(IInterface interface){
        _interface = interface;
    }
    public MyMethod(string str){
        return 2;
    }
}

//Abstract Class
public abstract class AbstractClass
{

 // This method gets called when i create the  instance of the derived class in my unit   
  test..

   protected AbstractedClass() : this(new SomeOtherClass()){
       DoSomethingElse();    /// I want to skip this method or mock it.
   }
 }
forsvarir
  • 10,749
  • 6
  • 46
  • 77
Dexterslab
  • 129
  • 1
  • 2
  • 14
  • You have a design issue. AbstractClass is hardcoding instantiation of a dependency in its ctor. If methods on this dependency are what you want to mock, you need to change the AbstractClass ctor to take in the dependency. If you can elaborate on what this method does internally, maybe you would get some better answers – Gishu May 26 '11 at 08:48

2 Answers2

7

By inheriting from the base class you are extending it. It is more about getting your code into a testable state rather than having Moq work for you.

  1. You can either use composition instead of a base class and then use dependency injection (via an interface) that you can mock.
  2. Or if you have to inherit then extract the logic that you don't want to run into another class that you inject again via dependency injection.
  3. Or have that logic that you don't want to run be part of a virtual method that you can mock. (like @Ohad Horesh's answer:)

    public virtual void DoSomethingElse();
    
    mock.Setup(abs => abs.Foo());  //here the mocked method will be called  
                                   // rather than the real one
    

If these options are not viable then you will either have to test that functionality through the derived class or use another mocking framework such as TypeMock Isolator, Moles or JustMock.

forsvarir
  • 10,749
  • 6
  • 46
  • 77
aqwert
  • 10,559
  • 2
  • 41
  • 61
4

Yes this is a pretty basic scenario in Moq.
Assuming your abstract class looks like this:

public class MyClass : AbstractBaseClass
{
    public override int Foo()
    {
        return 1;
    }
}

You can write the test below:

[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());
}
forsvarir
  • 10,749
  • 6
  • 46
  • 77
Ohad Horesh
  • 4,340
  • 6
  • 28
  • 45