3
votes

I'm building a website in MVC 4 & using Automapper to map from domain objects to Viewmodel objects. I have injected Automapper as stated here http://rical.blogspot.in/2012/06/mocking-automapper-in-unit-testing.html

and it's working fine inside action methods while debugging, but during unit testing the action method when I inject automapper service I find that service.map is returning null. But while debugging the mapping is fine. I'm not being able to find the reason, trying for over 4 hrs. I have a domain class called Interview & its corrosponding viewmodel as InterviewModel. I have initialized mapping as CreateMap(); in automapper profile config, that has been called from global startup method. Below is the controller & action...

public class NewsAndViewsController : Controller
{
    private IInterviewRepository repository;
    private IMappingService mappingService;

    public NewsAndViewsController(IInterviewRepository productRepository, IMappingService autoMapperMappingService)
    {
        repository = productRepository;
        mappingService = autoMapperMappingService;
    }

    [HttpPost, ValidateAntiForgeryToken]
    [UserId]
    public ActionResult Edit(InterviewModel interView, string userId)
    {
        if (ModelState.IsValid)
        {
            var interView1 = mappingService.Map<InterviewModel, Interview>(interView);
            **// THE ABOVE LINE RETURNING NULL WHILE RUNNING THE BELOW TEST, BUT NOT DURING DEBUGGING**
            repository.SaveInterview(interView1);
            TempData["message"] = string.Format("{0} has been saved", interView.Interviewee);
            return RedirectToAction("Create");
        }
        return View(interView);
    }
}

[TestMethod]
public void AddInterview()
{
    // Arrange
    var interviewRepository = new Mock<IInterviewRepository>();
    var mappingService = new Mock<IMappingService>();
    var im = new InterviewModel { Interviewee="sanjay", Interviewer="sanjay", Content="abc" };
    mappingService.Setup(m => m.Map<Interview, InterviewModel>(It.IsAny<Interview>())).Returns(im);
    var controller = new NewsAndViewsController(interviewRepository.Object, mappingService.Object);

    // Act
    var result = controller.Edit(im, "2") as ViewResult;

    // Assert - check the method result type
    Assert.IsNotInstanceOfType(result, typeof(ViewResult));
}
1
How do you know it's that particular line giving null? Have you stepped through the test? Your setup looks fine so I'm wondering if it's the View() or cast in the test that's not doing what you expect. - Mike Parkhill
@MikeParkhill I'm debugging the testmethod & interView1 is appearing null but I see that interView object has perfect value. Actually I'm setting another value after that line before save is called like interView1.CreatedDate = DateTime.Now... This line is throwing error while test method is executing but not during debugging the whole site :( - SanjayD
@MikeParkhill Well just found that while debugging mappingService is properly initialized to MySite.Infrastructure.Automapper.MappingService but while i debug the testmethod its showing of type Castle.Proxies.IMappingServiceProxy How is it happening? I guess I have messed with the namespace somewhere or any misconfiguration in test method!!! I'm also using ninject for DI. - SanjayD
The below line in test method is working fine var mappingService = new Mock<MySite.Infrastructure.Automapper.IMappingService>(); But while calling the controller var controller = new NewsAndViewsController(interviewRepository.Object, mappingService.Object) mappingService.Object is returning Castle.Proxies.IMappingServiceProxy. I'm clue less now. :( - SanjayD
All Mock<> objects show up as Castle.Proxies.*. It's the namespace Moq uses to build the proxy class for your interface. - Mike Parkhill

1 Answers

2
votes

In your test you've got your Interview and InterviewModel classes crossed up in the mappingService.Setup() call (as an aside, I think you could use better naming conventions, or don't use var, to keep your objects clear - "im", "interview" and "interview1" don't make it easy to follow which is the model and which is the view object).

Try this:

[TestMethod]
public void AddInterview()
{
    // Arrange
    var interviewRepository = new Mock<IInterviewRepository>();
    var mappingService = new Mock<IMappingService>();
    var interview = new Interview();
    var im = new InterviewModel { Interviewee="sanjay", Interviewer="sanjay", Content="abc" };
    mappingService.Setup(m => m.Map<InterviewModel, Interview>(im).Returns(interview);
    var controller = new NewsAndViewsController(interviewRepository.Object, mappingService.Object);

    // Act
    var result = controller.Edit(im, "2") as ViewResult;

    // Assert - check the method result type
    Assert.IsNotInstanceOfType(result, typeof(ViewResult));
}