user1263981
user1263981

Reputation: 3157

IOC in UnitTest class - Unity.WebApi

I have implemented Unity.WebAPI in web api project successfully. Some how new instance of MService class is not being created. I get following error message when i run unit test method.

Unable to get default constructor for class MServiceTests.

Service Class

    private readonly IRepository _mRepository;

    public MService(IMRepository mRepository)
    {
        _mRepository = mRepository;
    }

     public List<FUser> GetFUser()
    {
      result = _mRepository.ExecuteCommandReader()
    }

Test Class

 public class MServiceTests
{
    private readonly IMRepository _mRepository;
    private readonly IMService _mService;


    public MServiceTests(IMRepository mRepository, IMService mService)
    {
        _mRepository = mRepository;
        _mService = mService;
    }




    [TestMethod]
    public void Get_Users_ReturnsUserList()
    {

        var resultList = new List<FUser>();
        resultList = _mService.GetFUser();

        Assert.IsTrue(resultList.Count > 0);

    }
}

UnityConfig

    container.RegisterType<IFService, FService>(new HierarchicalLifetimeManager());
    container.RegisterType<IMService, MService>(new HierarchicalLifetimeManager());
    container.RegisterType<ITransactionService, TransactionService>(new HierarchicalLifetimeManager());
    container.RegisterType<IMRepository, MRepository>();

Upvotes: 1

Views: 123

Answers (2)

Nkosi
Nkosi

Reputation: 247531

There seems to be a bit of confusion about how to unit test a class that has dependencies.

Let us assume the subject under test looks like this

public class MService: IMService {

    private readonly IMRepository mRepository;

    public MService(IMRepository mRepository) {
        this.mRepository = mRepository;
    }

    public List<FUser> GetFUser() {
        var result = mRepository.ExecuteCommandReader();
        return result
    }
}

In order to test the MService.GetFUser you would create an instance of the subject class MService and inject what ever dependencies are needed to test the behavior of the method under test.

In the following example test, the dependencies will be mocked using Moq mocking framework. You could just as easily create a fake implementation if so desired.

[TestClass]
public class MServiceTests {   
    [TestMethod]
    public void Get_Users_ReturnsUserList() {
        //Arrange 
        var expected = new List<FUser>() {
            //populate with some users
        };
        IMRepository mockRepository = new  Mock<IMRepository>();
        mockRepository.Setup(_ => _.ExecuteCommandReader()).Returns(expected);

        IMService mService = new MService(mockRepository.Object);

        //Act
        var resultList = mService.GetFUser();

        //Assert
        Assert.IsTrue(resultList.Count > 0);    
    }
}

The reason for your initial problem what the the test runner was unable to create the test class as it (the runner) was not build to do DI.

In order to test the subject class, you needed to create an instance of the class and inject any dependencies needed to test the behavior of the method under test.

There really was no need to use the container for such a small isolated test

Upvotes: 2

Silvos
Silvos

Reputation: 175

You are missing the [TestClass] attribute on the test class (assuming your are using MSTest framework). Test classes need to have an empty default constructor or no constructors at all.

For setting up the tests you can either arrange it the way that you

  1. Manually create the required instances or
  2. Use a mocking framework or
  3. Do the same initializations just like in your application regarding dependency injection, and then resolve the instances as required

Maybe you also want to take a look, at the Arrange-Act-Assert pattern for unit tests: (see http://defragdev.com/blog/?p=783)

Also keep in mind, that you rather want to test the code and not the DI framework.

Upvotes: 1

Related Questions