1

I'm just learning how dependency injection and mocking work, but I'd like some feedback on how I'm setting up a couple of tests. I can get them to pass, but I'm not sure this is all I need.

This is an MVC application that makes Web API calls to return data. For this example I'm running queries in the Web APIs that populate dropdowns.

Please give me any and all suggestions about what I'm doing right or wrong here or anything I should be doing differently.

Setup file for Dependency Injection - Unity.WebAPI (NuGet Package)

UnityConfig.cs

public static class UnityConfig
{
    public static void RegisterComponents()
    {
        var container = new UnityContainer();

        // register all your components with the container here
        // it is NOT necessary to register your controllers

        // e.g. container.RegisterType<ITestService, TestService>();

        container.RegisterType<IDropDownDataRepository, DropDownDataRepository>();

        GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
    }
}

CONTROLLER

public class DropDownDataController : ApiController
{  
    private IDropDownDataRepository _dropDownDataRepository;

    //Dependency Injection (I'm using Unity.WebAPI)
    public DropDownDataController(IDropDownDataRepository dropDownDataRepository)
    {
        _dropDownDataRepository = dropDownDataRepository;
    }

    [HttpGet]
    public HttpResponseMessage DateList()
    {
        try
        {
            return _dropDownDataRepository.DateList();
        }
        catch
        {
            throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
        }
    }
}

REPOSITORY

public class DropDownDataRepository : IDropDownDataRepository
{
    //Is this fine in here, or should it be injected somehow too?
    private MyDatabaseEntities db = new MyDatabaseEntities();  

    public HttpResponseMessage DateList()
    {
        var sourceQuery = (from p in db.MyProcedure()
                           select p).ToList();

        string result = JsonConvert.SerializeObject(sourceQuery);
        var response = new HttpResponseMessage();
        response.Content = new StringContent(result, System.Text.Encoding.Unicode, "application/json");

        return response;
    }
}

INTERFACE

public interface IDropDownDataRepository
{
    HttpResponseMessage DateList();
}  

UNIT TESTS

/// <summary>
/// Tests the DateList method is run
/// I pieced this kind of test together from examples online
/// I'm assuming this is good for a simple test
/// </summary>
[TestMethod]
public void DateListTest1()
{
    //Arrange
    var mockRepository = new Mock<IDropDownDataRepository>();
    mockRepository.Setup(x => x.DateList());           
    var controller = new DropDownDataController(mockRepository.Object);

    //Act
    controller.DateList();

    //Assert
    mockRepository.VerifyAll();
}



/// <summary>
/// Tests the DateList method returns correct status code.
/// This will run with success, but I'm not sure if that's just
/// because I'm telling it to return what I'm expecting.  
/// I welcome suggestions for improvement.
/// </summary>
[TestMethod]
public void DateListTest2()
{
    //Arrange
    var mockRepository = new Mock<IDropDownDataRepository>();
    mockRepository
        .Setup(x => x.DateList())
        //This will only succeed if I have the Returns property here,
        //but isn't that just bypassing the actual "test" of whether or
        //not this works?
        .Returns(new HttpResponseMessage(HttpStatusCode.OK));

    DropDownDataController controller = new DropDownDataController(mockRepository.Object);
    controller.Request = new HttpRequestMessage();
    controller.Configuration = new HttpConfiguration();

    //Act            
    var response = controller.DateList();

    //Assert
    Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
}

UPDATE 1

One of my main questions here is what the .Returns property actually does. In my second unit test, I'm telling it to return OK, then check if it returns OK. I can't see how that's actually testing anything.

madvora
  • 1,717
  • 7
  • 34
  • 49

1 Answers1

4

One of my main questions here is what the .Returns property actually does. In my second unit test, I'm telling it to return OK, then check if it returns OK. I can't see how that's actually testing anything.

The code:

mockRepository
        .Setup(x => x.DateList())
        //This will only succeed if I have the Returns property here,
        //but isn't that just bypassing the actual "test" of whether or
        //not this works?
        .Returns(new HttpResponseMessage(HttpStatusCode.OK));

Says that when the mockRepository recieves a call to DateList() then it should return a new HttpResponseMessage(HttpStatusCode.OK).

So inside

    [HttpGet]
    public HttpResponseMessage DateList()

when the unit test reaches the line

return _dropDownDataRepository.DateList();

The mocked object fires and returns new HttpResponseMessage(HttpStatusCode.OK)

A better name for this test would be instead of DateListTest2 something like DateList_Returns_Status_Code_From_Repository as that is what you're arranging in the test.

To be honest controller.DateList() doesn't have much logic so that's about the only golden path test you could have.

NikolaiDante
  • 18,469
  • 14
  • 77
  • 117
  • Thanks for the answer. I have another one based off this same setup, but a little more complicated involving Windows Authentication. I'd really appreciate if you could take a look. http://stackoverflow.com/questions/34519238/unit-testing-a-controller-that-uses-windows-authentication – madvora Jan 06 '16 at 18:14