the_endian
the_endian

Reputation: 2527

How to get at a model passed to RedirectToAction for Unit Test?

I have an ASP.NET MVC 5 controller with the following return statement:

return RedirectToAction("SendEmail",message);

Where message is an object of type Message. I would like to unit test that this controller is appropriately returning the message object, not just that it is returning to the SendEmail action (I've already written that test succesfully).

How can I check that the controller is properly returning a Message object as an argument to RedirectToAction? I am not able to get at it by simply trying:

 var result = controller.Save(mockMessage) as RedirectToRouteResult;

 //Assert
 Assert.IsInstanceOf<Message>(result.RouteValues);

I am familiar with RouteValues["action"] and RouteValues["controller"] but I have no idea how to check for a model, result.RouteValues["model"] doesn't work that way.

Full controller code:

 public ActionResult Save([Bind(Exclude = "Id")] Message message)
 {

     if (!ModelState.IsValid)
     {
         var viewModel = new MessageViewModel(message);
         return View("index",viewModel);
     }

     message.TimeStamp = DateTime.UtcNow;
     _messageRepository.Add(message);
     return RedirectToAction("SendEmail",message);
 }

Upvotes: 1

Views: 707

Answers (1)

Dominik Herold
Dominik Herold

Reputation: 194

If you like to use the Moq Framework you can define a virtual method in your controller class which calls the base.RedirectToAction

public virtual RedirectToRouteResult RedirectToAction(string actionName, Message message)
    {
        return base.RedirectToAction(actionName, message);
    }

This could be your test code:

[Test]
    public void it_should_do()
    {
        var myController = new Mock<MyController> { CallBase = true };
        myController.Save(myMessage);

        myController.Verify(m => m.RedirectToRouteResult(It.IsAny<string>(), It.IsAny<Message>()), Times.Once);
        myController.Verify(m => m.RedirectToRouteResult("SendEmail", myMessage), Times.Once);
    }

However this has the disadvantage of a public virtual method, but you can test if the Message object is taken.

Upvotes: 1

Related Questions