Massey
Massey

Reputation: 1125

Unit test result in null object while testing a web api 2

I am new to MS Unit Testing and Moq objects. I am trying to test my Web API 2 controller. I have given below my unit test and controller code. While stepping through the code, it doesn't even go to the GetDeliveryCodeStrategy method.

[TestMethod]
public void  CreateDelivery_ShouldReturnDeliveryCode()
{
    Mock<IDeliveryStrategy> deliveryStrategy = new Mock<IDeliveryStrategy> 
 ();
    Mock<IDeliveryCode> deliveryCode = new Mock<IDeliveryCode>();
    var controller = new DeliveryCodeController(deliveryStrategy.Object, 
    deliveryCode.Object);
    var controllerContext = new HttpControllerContext();
    var request = new HttpRequestMessage();
    request.Headers.Add("appToken", "a57ffa87-950e-40f4-b965-17788becac7d");

    controllerContext.Request = request;
    controller.ControllerContext = controllerContext;

    var result = controller.CreateDelivery(50) as 
    CreatedNegotiatedContentResult<IDeliveryCode>;
    Assert.IsNotNull(result);

}

public class DeliveryCodeController : ApiController
{
    IDeliveryStrategy _deliveryBatch;
    IDeliveryCode _deliveryCode;

    //Constructor dependency injection through Autofac
   public DeliveryCodeController(IDeliveryStrategy DeliveryBatch, 
   IDeliveryCode deliveryCode)
   {
        _deliveryBatch = DeliveryBatch;
        _deliveryCode = deliveryCode;
   }

   [HttpPost]
   [Route("api/DeliveryCode/{percentage}")]
   public IHttpActionResult CreateDelivery(int percentage)
   {
      String appToken = String.Empty;

    if (Request.Headers.TryGetValues("appToken", out IEnumerable<String> 
    headerValues))
    {
    appToken = headerValues.FirstOrDefault();
    }
    if (!String.IsNullOrEmpty(appToken)))
    {   
    IDeliveryContext deliveryContext = 
       _deliveryBatch.GetDeliveryCodeStrategy(percentage);  
    _deliveryCode.Code = deliveryContext.Create();
    return Created(Request.RequestUri.ToString(), _deliveryCode);    
    }
    else
    {
    return Content(HttpStatusCode.Forbidden, new Error { message = "The App 
    Token is not valid." });
    }
  }

}

When I do the "Debug Test" and step through the code, the deliveryContext object comes as null in the code IDeliveryContext deliveryContext = _deliveryBatch.GetDeliveryCodeStrategy(percentage);

Upvotes: 0

Views: 502

Answers (2)

Stefan
Stefan

Reputation: 21

You need to call Setup() on mock objects for the methods that you want to use:

var deliveryStrategy = new Mock<IDeliveryStrategy>();
deliveryStrategy.Setup(x => x.GetDeliveryCodeStrategy(It.IsAny<int>))
    .Returns(AMockOfDeliveryContext); //you need to mock it beforehand so you can 
                                      //use the object here

Upvotes: 0

Scott Hannen
Scott Hannen

Reputation: 29222

You have to set up the Mock to return a certain value:

IDeliveryContext deliveryContext = // ???? - whatever you want it to be. 
                                   // Could be another Mock.
                                   // This is what the Mock will return.

Mock<IDeliveryStrategy> deliveryStrategy = new Mock<IDeliveryStrategy>();
deliveryStrategy.Setup(x => x.GetDeliveryCodeStrategy(It.IsAny<decimal>()))
    .Returns(deliveryContext);

This tells the Mock that that when its GetDeliveryCodeStrategy method is called, it should return the specified IDeliveryContext. Depending on what you're trying to do, that could be another Mock. (Mocks that return mocks are undesirable, but if you're starting out I'd file that detail away and come back to it.)

I'm guessing that percentage is a decimal. It.IsAny<decimal>() means that the mock doesn't care what the value is. That's usually okay because what you're testing is what your class does with the object returned by the mock.

Upvotes: 1

Related Questions