Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit testing a class that inherits from an abstract class

My problem is that I want to stub a property in my abstract class, because my class in test uses that property. I'm currently using latest version of Moq.

My abstract class looks like this:

public abstract class BaseService
{
    protected IDrawingSystemUow Uow { get; set; }
}

And my class in test looks like this:

public class UserService : BaseService, IUserService
{
    public bool UserExists(Model model)
    {
        var user = this.Uow.Users.Find(model.Id);
        if(user == null) { return false; }

        reurn true;
    }
}

I can't figure out how I can stub the Uow property. Does anybody have any clue? Or is my design that bad that I need to move to Uow property to my class in test?

like image 201
Rikard Avatar asked Sep 16 '12 21:09

Rikard


People also ask

Can you unit test an abstract class?

The answer is: always test only concrete classes; don't test abstract classes directly . The reason is that abstract classes are implementation details. From the client perspective, it doesn't matter how Student or Professor implement their GetSignature() methods.

Can you inherit a class from an abstract class?

An abstract class cannot be inherited by structures. It can contain constructors or destructors. It can implement functions with non-Abstract methods. It cannot support multiple inheritances.

Which class should a class inherit from abstract?

If the Child class is unable to provide implementation to all abstract methods of the Parent class then we should declare that Child class as abstract so that the next level Child class should provide implementation to the remaining abstract method.

Can you inherit from an abstract class and an interface?

An abstract class defines the identity of a class. An interface can inherit multiple interfaces but cannot inherit a class. An abstract class can inherit a class and multiple interfaces. An interface cannot declare constructors or destructors.


1 Answers

Your current setup won't work for one simple reason - Uow property is non-overridable and Moq's job is done at this point. Cannot override, cannot mock.

Easiest solution is to simply make that property overridable. Change your base class definition to:

public abstract class BaseService
{
    protected virtual IDrawingSystemUow Uow { get; set; }
}

Now you can use Moq's protected feature (this requires you to include using Moq.Protected namespace in your test class):

// at the top of the file
using Moq.Protected;

// ...

var drawingSystemStub = new Mock<IDrawingSystemUow>();
var testedClass = new Mock<UserService>();
testedClass 
  .Protected()
  .Setup<IDrawingSystemUow>("Uow")
  .Returns(drawingSystemStub.Object);

// setup drawingSystemStub as any other stub

// exercise test
var result = testedClass.Object.UserExists(...);
like image 164
k.m Avatar answered Sep 22 '22 01:09

k.m