0

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

1
  • 1
    When you say "it doesn't even go to the GetDeliveryCodeStrategy method" - you've mocked out the IDeliveryStrategy, so it's not clear what you expect it to do. (It would also really help if you'd format the code you're presenting here - the indentation of CreateDelivery is very hard to read.) Commented Jan 16, 2019 at 17:11

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.