Search code examples
c#dependency-injectioninversion-of-controlninject

Inject Dependency without using Constructor injection using Ninject - Unit Tests


I am creating Unit Tests for existing .NET Framework 4.5 API project. The existing project has parameterless constructor by design and dependency injection was implemented as per the class below using Ninject.

I would like to Mock the interface and create an instance of the class for testing as shown below but the constructor is parameterless. I can't figure out how to inject my Mock member.Object. The main goal is I don't want to change the design of existing classes unless there is no other way.

public class MemberController : ApiController
{
    StandardKernel DependencyKernel;
    private IMember member;
    
    public MemberController()
    {
        DependencyKernel = new StandardKernel();
        DependencyKernel.Load(Assembly.GetExecutingAssembly());
        member = DependencyKernel.Get<IMember>();
    }

    [HttpPost]
    public HttpResponseMessage AddMember(MemberRequest model)
    {
        try
        {
            int memberRecords;
            
            member.SaveMember(model, out memberRecords);

            if (memberRecords > 0)
                return new HttpResponseMessage { StatusCode = HttpStatusCode.Conflict, Content = new StringContent("Member with same reference exists") };
            else
                return new HttpResponseMessage { StatusCode = HttpStatusCode.OK, Content = new StringContent("Member added successfully") };
        }
        catch (Exception ex)
        {
            return new HttpResponseMessage { StatusCode = HttpStatusCode.InternalServerError, Content = new StringContent(ex.Message) };
        }
    }
}

//Test Class

public class MemberControllerTests
{
    StandardKernel DependencyKernel;
    private MemberController memberController;
    Mock<IMember> member = new Mock<IMember>();

    public MemberControllerTests()
    {
        DependencyKernel = new StandardKernel();
        DependencyKernel.Load(Assembly.GetExecutingAssembly());
    }

    [SetUp]
    public void Setup()
    {
        
    }

    [Test]
    public void should_AddMember()
    {
        //Arrange
        MemberRequest member = new MemberRequest{ };
        int memberRecords;

        member.Setup(x => x.SaveMember(member, out memberRecords));

        memberController = new MemberController(member.Object); //This will obviously not work, the MemberController has parameterless constructor
        //Act
        var result = MemberController.AddMember(member);
        //Assert
        Assert.AreEqual(result.StatusCode, HttpStatusCode.OK);
    }
}

Solution

  • This post has the answer to the question. If IMember member property is made public in MemberController, I can new up the MemberController class and set the value of its member property to the MOCK.