Search code examples
c#unit-testingasp.net-web-apiinversion-of-control

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>();

Solution

  • 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