Moq Automapper service in testmethod returns null while mapping - asp.net-mvc

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

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

Related

Unit Testing With Dependency Injection and MOQ

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.
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.

Testing a MVC Controller fails with NULL reference exception

Below is the setup that I am trying to test.
The controller:
public ActionResult UpsertStudent(StudentModel studentModel)
{
try
{
if (!CheckStudentUpdateForEdit(studentModel))
{
return Json(new { result = STUDENT_EXISTS });
}
// remaining code removed for brevity
}
private bool CheckStudentUpdateForEdit(StudentModel studentModel)
{
var returnVal = true;
var existingStudent = _updateStudentManager.GetStudentInfo(studentModel.Id);
if (existingStudent.StudentType == "Day Scholar")
{
returnVal = true;
}
else
{
returnVal = false;
}
return returnVal;
}
The Test method:
public void AllowStudentUpdates_Success()
{
var studentModel = new StudentModel()
{
StudentName = "Joe",
Id = "123",
StudentType = "Day Scholar"
};
var studentToAdd = new Student()
{
Id = "123",
Name = "Joe",
StartDate = DateTime.UtcNow.ToShortDateString(),
StudentType = "Day Scholar",
EndDate = "08/10/2016"
};
_studentRulesHelper.Setup(x => x.GetStudentRule(studentModel, true)).Returns(studentToAdd);
_productRulesHelper.Setup(x => x.ReturnStudentRule(studentModel, true)).Returns(studentToAdd);
var res = _controller.UpsertStudent(studentModel) as JsonResult;
if (res != null) Assert.AreEqual("{ result = True }", res.Data.ToString());
}
When it hits the UpsertDoc call, it goes to the actual call in the controller and tries to execute CheckStudentUpdateForEdit() the GetStudentInfo() tries to get an object from the db and returns a null object as there is no student with the id that's passed from the test method.
The test then fails with Null Reference exception.
Now the system under test is not supposed to hit the db. I don't know why this is doing the other way!
Anyone else writing this test will also try to pass a dummy object which is bound to fail at GetStudentInfo() the way the test is setup now.
What do I do to make this work?
I am not sure if I have understood you problem correctly, but looking at the code snippets provided, the test will go and hit the database, because the mock object and its expectation is not defined.
I would have implemented the solution like this -
I am making some assumptions that your _updateStudentManager object is for the class that is doing the DB interaction for Student. I'll call it say StudentRepository. And to allow you to mock the behavior I would make it Interface driven.
So typically my setup would look like this -
//Interface
public interface IStudentrepository
{
StudentModel GetStudentInfo(int studentId);
}
//Class implementing IStudentrepository
public class StudentRepository : IStudentrepository
{
public StudentModel GetStudentInfo(int studentId)
{
//Implementation goes here
}
}
Now in my controller, I would have an instance of IStudentrepository, which can be injected via constructor.
public class StudentController
{
private readonly IStudentrepository updateStudentManager;
public StudentController(IStudentrepository updateStudentManager)
{
this.updateStudentManager = updateStudentManager;
}
}
//Rest of the code for controller....
Now while writing my Test, I will create a mock object of IStudentrepository, define the expectation for the mock object, and inject it when creating the controller object. Something like this.
[TestMethod]
public void TestMethod1()
{
//--Arrange--
//Define a mock object for student repository
var mock = new Mock<IStudentrepository>();
//Define the expectations of the mock object
mock.Setup(s => s.GetStudentInfo(It.IsAny<int>()))
.Returns(new StudentModel {/*return the required object */ });
//Instantiate controller and inject the mock object
StudentController _controller = new StudentController(mock.Object);
//--Act--
var res = _controller.UpsertStudent(studentModel) as JsonResult;
//--Assert--
if (res != null) Assert.AreEqual("{ result = True }", res.Data.ToString());
}
Now when your test method calls the GetStudentInfo method, instead of hitting the db, it will return the value as set in mock object.
This is just a high level implementation, and of course you can modify it as per your design. Hope it helps

Autofac Automocking in ASP.NET MVC

So I'm trying to use Autofac Automocking in ASP.NET MVC 5, but for some reason I can't get it to work.
Here's the test so far:
using (var mock = AutoMock.GetLoose())
{
const string mainUserID = "MainUserID";
const string otherUserID = "OtherUserID";
ApplicationUser user = new ApplicationUser()
{
Id = mainUserID,
UserName = "TestUser"
};
var dataProvider = mock.Mock<IDataProtectionProvider>();
dataProvider.DefaultValue = DefaultValue.Mock;
var userManagerMock = mock.Mock<ApplicationUserManager>();
}
The test fails when mocking the ApplicationUserManager. The error is this:
Result StackTrace:
at Autofac.Extras.Moq.AutoMock.Mock[T](Parameter[] parameters)
at AwenterWeb_NUnit.AccountControllerTest.<Deactivate_User>d__0.MoveNext() in C:\Users\Fabis\Documents\Docs\Kvalifikācijas darbs 2015\AwenterWeb\AwenterWeb-NUnit\AccountControllerTest.cs:line 51
at NUnit.Framework.AsyncInvocationRegion.AsyncTaskInvocationRegion.WaitForPendingOperationsToComplete(Object invocationResult)
at NUnit.Core.NUnitAsyncTestMethod.RunTestMethod()
Result Message: System.InvalidCastException : Unable to cast object of type 'AwenterWeb.ApplicationUserManager' to type 'Moq.IMocked`1[AwenterWeb.ApplicationUserManager]'.
The same thing happens when trying to automock the ApplicationDbContext and it has a very simple constructor, so there shouldn't even be any issues with it.
I'm new to Mocking - what should I do in this scenario?
Edit: Also kind of an unrelated question, maybe you guys know - I've noticed that when creating a Moq for a DbSet using a list created previously in the test, I have to do this:
var dbSetMock = new Mock<IDbSet<DbEntity>>();
dbSetMock.Setup(m => m.Provider).Returns(data.Provider);
dbSetMock.Setup(m => m.Expression).Returns(data.Expression);
dbSetMock.Setup(m => m.ElementType).Returns(data.ElementType);
dbSetMock.Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());
It seems really unintuitive. Is there a way to just tell the mock to take the list? So something like:
dbSetMock.Setup(m => m).Returns(data);
Or any other way to create a DbSet Moq from an existing list quickly without having to write those 4 extra lines?
If you look at ligne 73 of MoqRegistrationHandler.cs you can see that only interface is moqable using Autofac.Extras.Moq
var typedService = service as TypedService;
if (typedService == null ||
!typedService.ServiceType.IsInterface ||
typedService.ServiceType.IsGenericType && typedService.ServiceType.GetGenericTypeDefinition() == typeof(IEnumerable<>) ||
typedService.ServiceType.IsArray ||
typeof(IStartable).IsAssignableFrom(typedService.ServiceType))
return Enumerable.Empty<IComponentRegistration>();
var rb = RegistrationBuilder.ForDelegate((c, p) => CreateMock(c, typedService))
.As(service)
.InstancePerLifetimeScope();
You can change the code but it may be quite difficult to make it works with non parameter less dependency.
Can your dependencies be changed to use an interface instead of a concrete class ? if it is not possible and/or if it doesn't make sense, you can use the MockRepository to create your non parameter-less component and then inject it on the AutoMock class.
class Program
{
static void Main(string[] args)
{
using (var mock = AutoMock.GetLoose())
{
/// configure your non interface component with constructor parameters
/// if foo need more complex parameters you can get them
/// using mock.Mock<T>().Object
var fooMock = mock.MockRepository.Create<Foo>((String)null);
fooMock.SetupGet(f => f.Value).Returns("test");
// insert your instance into the container
mock.Provide<Foo>(fooMock.Object);
var bar = mock.Create<Bar>();
Console.WriteLine(bar.GetValue());
}
}
}
public class Foo
{
public Foo(String value)
{
this._value = value;
}
private readonly String _value;
public virtual String Value
{
get
{
return this._value;
}
}
}
public interface IBar
{
String GetValue();
}
public class Bar : IBar
{
public Bar(Foo foo)
{
this._foo = foo;
}
private readonly Foo _foo;
public String GetValue()
{
return this._foo.Value;
}
}
It is not a perfect solution but without big refactoring of the Autofac.Extras.Moq project I can't see any simpler way to do it.

Model missing when unit testing MVC 5 async controller methods

Here is my controller method:
private IAutoManagerUnitOfWork _work;
public VehiclesController(IAutoManagerUnitOfWork work)
{
_work = work;
}
public async Task<ViewResult> Index()
{
return View("Index", await _work.VehicleRepository.GetAll().ToListAsync());
}
Here is my NUnit test method:
[Test]
public async Task Index_Get_ReturnsViewResult()
{
MockUnitOfWork uow = new MockUnitOfWork();
uow.VehicleRepository.Add(new Vehicle { Year = 2011, Make = "Ford", Model = "Mustang", Trim = "GT" });
var controller = new VehiclesController(uow);
ViewResult viewResult = await controller.Index();
var model = (List<Vehicle>)(viewResult.Model);
Assert.IsTrue(model.Count > 0); // Causes exception because model isn't defined.
}
When I step through the test, viewResult.Model is empty (has a Count = 0). I've tried making my test method non-async and doing a task.Wait() after the call to Index(), but the only way I can get it to work is by changing my controller method to a non-async method. I found a couple of examples here on Stack Overflow, but even following those I can't get it to work. What am I doing wrong?

Testing an Edit view with MVCContrib Test Helper

I am using ASP.NET MVC 3, MVCContrib, NUnit and Rhino Mocks. I have posted this but could not get an answer. People are focusing more on my coding that helping me get a decent answer to get this test to pass.
I am trying to test my Edit view. I'm not sure how to code the test for the view. It is a strongly typed view of type NewsEditViewData.
When the view loads, it gets a news item's data by ID from the news service. So in my test I created a stub of the news service:
var id = 1;
var news = new News();
newsServiceStub
.Stub(x => x.FindById(id))
.Return(news);
Now I need to map this news item to NewsEditViewData. I have a mapper (AutoMapper) that does this for me, and in my test I did the following:
newsMapperStub
.Stub(x => x.Map(news, typeof(News), typeof(NewsEditViewData)))
.Return(newsEditViewData);
I'm not sure if I am on the right track so far?
Then I have the following piece of code:
// Act
var actual = sut.Edit(id);
Don't work from my code, I want an answer following best practices. So what all do I need to check for in my assert part? Do I need to also check that a record was returned? I was thinking in the lines of something like:
actual
.AssertViewRendered()
.WithViewData<NewsEditViewData>()
.ShouldBe(newsEditViewData);
This fails. Can someone please help me rewrite this test so that it passes. I want it to check all that needs to be checked.
Here is the full test:
[Test]
public void Edit_should_render_Edit_view()
{
// Arrange
var id = 1;
var news = new News();
var newsEditViewData = new NewsEditViewData();
newsServiceStub
.Stub(x => x.FindById(id))
.Return(news);
newsMapperStub
.Stub(x => x.Map(news, typeof(News), typeof(NewsEditViewData)))
.Return(newsEditViewData);
// Act
var actual = sut.Edit(id);
// Assert
actual
.AssertViewRendered()
.WithViewData<NewsEditViewData>()
.ShouldBe(newsEditViewData);
}
UPDATE 2011-02-14:
In my NewsController I have the following:
private INewsService newsService;
private IMapper newsMapper;
public NewsController(INewsService newsService)
{
Check.Argument.IsNotNull(newsService, "newsService");
this.newsService = newsService;
newsMapper = new NewsMapper(); // TODO: Use dependency injection
}
The action method looks like this:
public ActionResult Edit(int id)
{
Check.Argument.IsNotZeroOrNegative(id, "id");
var news = newsService.FindById(id);
var newsEditViewData = (NewsEditViewData)newsMapper.Map(news, typeof(News), typeof(NewsEditViewData));
return View(newsEditViewData);
}
The error that I am getting in NUnit is:
MyProject.Web.UnitTests.Controllers.NewsControllerTests.Edit_RenderView_EditView:
MvcContrib.TestHelper.AssertionException : was MyProject.Web.Common.ViewData.NewsEditViewData but expected MyProject.Web.Common.ViewData.NewsEditViewData
You haven't shown none of your controller, repository, models. It's a question that is close to impossible to answer without this information. So lets start guessing. You have a model and a view model:
public class News { }
public class NewsEditViewData { }
I am leaving them without any properties for the purpose of this post. Then you probably have a service which is responsible for retrieving and saving your model (the view model should never appear as in/out argument of your service layer). The service should never know about the view model:
public interface INewsService
{
News FindById(int id);
void CreateNews(News news);
}
Then you probably have a mapper:
public interface IMapper
{
object Map(object source, Type sourceType, Type destinationType);
}
And finally I suppose that you have a controller that you are trying to test:
public class NewsController : Controller
{
private readonly INewsService _newsService;
private readonly IMapper _newsMapper;
public NewsController(INewsService newsService, IMapper newsMapper)
{
_newsService = newsService;
_newsMapper = newsMapper;
}
public ActionResult Edit(int id)
{
// WARNING: Meaningless action ahead as it retrieves some
// model from the service and passes this model to
// the service back again for update. In the meantime
// the model is converted to a view model using a mapper
// and passed to the view. So totally meaningless in a real
// application but let's consider for the purpose of this demonstration
var news = _newsService.FindById(id);
_newsService.CreateNews(news);
var newsEditViewData = (NewsEditViewData)_newsMapper.Map(news, typeof(News), typeof(NewsEditViewData));
return View(newsEditViewData);
}
}
OK, up until here it is you that should have provided this information.
And now I can start answering your question about the unit test which might look like this:
[Test]
public void Edit_should_fetch_news_model_from_service_given_an_id_parameter_create_news_and_pass_a_viewmodel_to_the_view()
{
// arrange
// TODO : move this part in the initialization section
// of your unit test to avoid repeating it on each method
var newsServiceStub = MockRepository.GenerateStub<INewsService>();
var newsMapperStub = MockRepository.GenerateStub<IMapper>();
var sut = new NewsController(newsServiceStub, newsMapperStub);
new TestControllerBuilder().InitializeController(sut);
var news = new News();
var id = 123;
var newsEditViewData = new NewsEditViewData();
newsServiceStub
.Stub(x => x.FindById(id))
.Return(news);
newsMapperStub
.Stub(x => x.Map(news, typeof(News), typeof(NewsEditViewData)))
.Return(newsEditViewData);
// act
var actual = sut.Edit(id);
// assert
actual
.AssertViewRendered()
.WithViewData<NewsEditViewData>()
.ShouldBe(newsEditViewData);
newsServiceStub.AssertWasCalled(x => x.CreateNews(news));
}

Resources