I've never used any Mock frameworks and actually new to ASP.NET MVC, testing and all this related stuff.
I'm trying to figure out how to use Moq framework for testing, but can't make it work. that's what I have at the moment: My repository interface:
public interface IUserRepository {
string GetUserEmail();
bool UserIsLoggedIn();
ViewModels.User CurrentUser();
void SaveUserToDb(ViewModels.RegisterUser viewUser);
bool LogOff();
bool LogOn(LogOnModel model);
bool ChangePassword(ChangePasswordModel model);
}
My Controller constuctor, I'm using Ninject for injection, it works fine
private readonly IUserRepository _userRepository;
public HomeController(IUserRepository userRepository) {
_userRepository = userRepository;
}
Simplest method in controller:
public ActionResult Index() {
ViewBag.UserEmail = _userRepository.GetUserEmail();
return View();
}
And my test method:
[TestMethod]
public void Index_Action_Test() {
// Arrange
string email = "test#test.com";
var rep = new Mock<IUserRepository>();
rep.Setup(r => r.GetUserEmail()).Returns(email);
var controller = new HomeController(rep.Object);
// Act
string result = controller.ViewBag.UserEmail;
// Assert
Assert.AreEqual(email, result);
}
I assume that this test must pass, but it fails with message Assert.AreEqual failed. Expected:<test#test.com>. Actual:<(null)>.
What am I doing wrong?
Thanks
Simple - you do not do Act part correctly. Fisrt you should call Index() action of the controller, and then Assert ViewBag.UserEmail correctness
// Act
controller.Index();
string result = controller.ViewBag.UserEmail;
By the way, advice - Using ViewBag is not the good practice. Define ViewModels instead
Related
I am learning to use unit testing and Moq for ASP.NET MVC 5. I am trying to write my first unit test for the index action of one of my controllers.
Here is the code for the index action.
[Authorize]
public class ExpenseController : Controller
{
private ApplicationDbContext db = new ApplicationDbContext();
// GET: /Expense/
public ActionResult Index()
{
return View(db.Expenses.ToList().Where(m => m.ApplicationUserId == User.Identity.GetUserId()));
}
}
All I want to do is just check that the returned view is not null
Something like this
[TestMethod]
public void ExpenseIndex()
{
// Arrange
ExpenseController controller = new ExpenseController();
// Act
ViewResult result = controller.Index() as ViewResult;
// Assert
Assert.IsNotNull(result);
}
Of course, this is not working because of the connecting to the database and the using of the ApplicationUserId so would you guys help me to moq and unit test this action or recommend me a tutorial where I can get familiar with mocking in ASP.NET MVC.
One way to do this is to abstract encapsulate the dependency in a virtual method, for example: Create a virtual method that returns the user expenses, now your controller should look like:
public class ExpenseController : Controller
{
private ApplicationDbContext db = new ApplicationDbContext();
// GET: /Expense/
public ActionResult Index()
{
return View(GetUserExpenses());
}
protected virtual List<Expense> GetUserExpenses()
{
return db.Expenses.ToList().Where(m => m.ApplicationUserId == User.Identity.GetUserId());
}
}
Then, create a stub class, that is derived from your controller, and override the GetUserExpenses() method. It should look like:
public class ExpenseControllerStub : ExpenseController
{
protected override List<Expense> GetUserExpenses()
{
return new List<Expense>();
}
}
Now in your unit test, create the instance from ExpenseControllerStub not from ExpenseController, and it should work:
[TestMethod]
public void ExpenseIndex()
{
// Arrange
ExpenseControllerStub controller = new ExpenseControllerStub();
// Act
ViewResult result = controller.Index() as ViewResult;
// Assert
Assert.IsNotNull(result);
}
This is how to do it manually. If you need to use a mocking framework for this, you will need to make GetUserExpenses() public not protected, then make a setup to return an empty expenses list, something like:
var mock = new Moq.Mock<ExpenseController>();
mock.Setup(m => m.GetUserExpenses().Returns(new List<Expense>());
But I don't prefer to make this method public! may be there is a way for Moq to configure/setup protected methods, but I am not aware of it.
Edit: A more better solution is to totally abstract the Expenses repository, in this case mocking it will be straight forward.
Another solution is to inject the DbContext to the controller constructor, and use a mocking framework to mock it and the Expenses DbSet. You can find a sample for doing this here
Edit#2: You may also use TestStack.FluentMVCTesting or MvcContrib.TestHelper to make you MVC testing easier.
Just wanted some guidance how would I go about unit testing the following action:
public ActionResult Index()
{
var model = _resolver.GetService<ISignUpViewModel>();
model.Location = _resolver.GetService<ILocations>().getLocations(string area);
return PartialView("Login", model);
}
private IDependencyResolver _resolverMock;
[TestMethod]
public void SignUpTest()
{
var _resolverMock = new Mock<IDependencyResolver>();
var ctrl = new HomeController(_resolverMock.Object);
var signUpMock = new Mock<ISignUpViewModel>();
var LocationsMock = new Mock<ILocations>();
_resolverMock.Setup(m => m.GetService(It.IsAny<Type>())).Returns(
signUpMock.Object);
_resolverMock.Setup(m => m.GetService(It.IsAny<Type>())).Returns(
LocationsMock.Object);
DependencyResolver.SetResolver(resolverMock.Object);
ctrl.Index();
ctrl.ViewData.Model = signUpMock;
}
How do you build up the model in the unit test?
Also how do I call the getLocations method from the resolver?
Unsure on how to do this?
Your home controller is not dependent on an IDependencyResolver as per your code. It is in fact dependent on an ISignUpViewModel. So you can either pass one of those into the constructor or an ISignUpViewModelFactory. So I would refactor the model resolution out into a factory class:
public class HomeController {
private readonly ISignUpViewModelFactory _modelFactory;
public HomeController(ISignUpViewModelFactory modelFactory){
_modelFactory = modelFactory;
}
public ActionResult Index()
{
return PartialView("Login", _modelFactory.Create(area));
}
}
public interface ISignUpViewModelFactory {
ISignUpViewModel Create(string area);
}
public class ProductionSignUpViewModelFactory : ISignUpViewModelFactory
{
public ISignUpViewModel Create(string area){
// create and return your models here
// if you still have to use a service locator in this factory then
// refactor some more until you get these dependencies out in the open.
}
}
public class MockSignUpViewModelFactory : ISignUpViewModelFactory
{
public ISignUpViewModel Create(string area){
return new SignUpViewModel();
}
}
In production you have your IOC inject an instance of ProductionSignUpViewModelFactory. In test, you pass in a MockSignUpViewModelFactory.
The difference is that using this method you are only testing the action (i.e. the unit) whereas using your current method you are testing the action AND your servicelocator _resolver plus you've obscured the actual dependency i.e. ISignUpViewModel not IDependencyResolver.
As per the comments in ProductionSignUpViewModelFactory, if you have to inject an IDependencyResolver into that factory to make it work then you're probably still doing it wrong. You then need to look at what ProductionSignUpViewModelFactory needs to create an instance of ISignUpViewModel and inject that not an IDependencyResolver.
Eventually you'll get to the top of your dependency chain and you'll find unit testing becomes very, very easy. It's even easier if you build the tests first i.e. TDD. :)
I'm getting my feet wet with unit testing (TDD). I have a basic repository pattern I'm looking to test and I'm not really sure I'm doing things correctly. At this stage I'm testing my domain and not worrying about controllers and views. To keep it simple here is a demo project.
Class
public class Person
{
public int PersonID { get; set; }
public string Name{ get; set; }
}
Interface
public interface IPersonRepository
{
int Add(Person person);
}
Concrete
public class PersonnRepository : IPersonRepository
{
DBContext ctx = new DBContext();
public int Add(Person person)
{
// New entity
ctx.People.Add(person);
ctx.SaveChanges();
return person.id;
}
}
I've added NUnit and MOQ to my test project and want to know how to properly test the functionality.
I'm not sure it's right but after reading some blogs I ended up creating a FakeRepository, however if I test based on this, how is that validating my actual interface?
public class FakePersonRepository
{
Dictionary<int, Person> People = new Dictionary<int, Person>();
public int Add(Person person)
{
int id = People.Count + 1;
People.Add(id, person);
return id;
}
}
then tested with
[Test]
public void Creating_A_Person_Should_Return_The_ID ()
{
FakePersonRepository repository = new FakePersonRepository();
int id = repository.Add(new Person { Name = "Some Name" });
Assert.IsNotNull(id);
}
Am I anywhere close to testing in the correct manor?
I'd like to test things like not passing a name causes error etc in the future.
Am I anywhere close to testing in the correct manor?
I am afraid that you are not. The idea of having an interface is that it allows you to decouple other code that uses a repository such your controller and be able to unit test it in isolation. So let's suppose that you have the following controller that you want to unit test:
public class PersonController : Controller
{
private readonly IPersonRepository _repo;
public PersonController(IPersonRepository repo)
{
_repo = repo;
}
[HttpPost]
public ActionResult Create(Person p)
{
if (!ModelState.IsValid)
{
return View(p);
}
var id = _repo.Add(p);
return Json(new { id = id });
}
}
Notice how the controller doesn't depend on a specific repository implementation. All needs is that this repository implements the given contract. Now we could use a mocking framework such as Moq in the unit test to provide a fake repository and make it behave as we like in order to test the 2 possible paths in the Create action:
[TestMethod]
public void PersonsController_Create_Action_Should_Return_View_And_Not_Call_Repository_If_ModelState_Is_Invalid()
{
// arrange
var fakeRepo = new Mock<IPersonRepository>();
var sut = new PersonController(fakeRepo.Object);
var p = new Person();
sut.ModelState.AddModelError("Name", "The name cannot be empty");
fakeRepo.Setup(x => x.Add(p)).Throws(new Exception("Shouldn't be called."));
// act
var actual = sut.Create(p);
// assert
Assert.IsInstanceOfType(actual, typeof(ViewResult));
}
[TestMethod]
public void PersonsController_Create_Action_Call_Repository()
{
// arrange
var fakeRepo = new Mock<IPersonRepository>();
var sut = new PersonController(fakeRepo.Object);
var p = new Person();
fakeRepo.Setup(x => x.Add(p)).Returns(5).Verifiable();
// act
var actual = sut.Create(p);
// assert
Assert.IsInstanceOfType(actual, typeof(JsonResult));
var jsonResult = (JsonResult)actual;
var data = new RouteValueDictionary(jsonResult.Data);
Assert.AreEqual(5, data["id"]);
fakeRepo.Verify();
}
You need to make your DBContext injectable by extracting an interface for it:
public interface IDBContext{
IList<Person> People {get;} // I'm guessing at the types
void SaveChanges();
// etc.
}
Then inject that into your concrete class:
public class PersonRepository : IPersonRepository
{
IDBContext ctx;
public PersonRepository(IDBContext db) {
ctx = db;
}
public int Add(Person person)
{
// New entity
ctx.People.Add(person);
ctx.SaveChanges();
return person.id;
}
}
Your test would then look like:
[Test]
public void Creating_A_Person_Should_Return_The_ID ()
{
Mock<IDBContext> mockDbContext = new Mock<IDBContext>();
// Setup whatever mock values/callbacks you need
PersonRepository repository = new PersonRepository(mockDbContext.Object);
int id = repository.Add(new Person { Name = "Some Name" });
Assert.IsNotNull(id);
// verify that expected calls are made against your mock
mockDbContext.Verify( db => db.SaveChanges(), Times.Once());
//...
}
I'd personally look at writing an "integration test" for this, i.e. one that hits a real (ish) database as your data access layer should not contain any logic which makes testing in isolation worthwhile.
In this case you will require a database up and running. This could be a developer database already set up somewhere, or an in-memory database started as part of the tests arrange.
The reason for this is that I find (pure) unit tests of the DAL generally end up as proof you can use a mock framework and little more and don't end up giving you much confidence in your code.
If you are completely new to unit tests and don't have colleges on hand to help set up the environment required for DAL testing you then I'd recommend you leave testing the DAL for now and concentrate on the business logic as this is where you will get the biggest bang for your buck and will make it easier see how the tests will help you.
I'm using ASP.NET MVC 2, NUnit, Moq and MVC Contrib. I have written my first unit test ever, and I have a couple of questions regarding this test. My scenario is that I have an Index view. On this view I have a grid that displays all the news items.
Here is my INewsRepository class:
public interface INewsRepository
{
IEnumerable<News> FindAll();
}
My test class with the test method:
public class NewsControllerTest :TestControllerBuilder
{
private Mock<INewsRepository> mockNewsRepository;
private NewsController newsController;
[SetUp]
public void Init()
{
mockNewsRepository = new Mock<INewsRepository>();
newsController = new NewsController(mockNewsRepository.Object);
InitializeController(newsController);
}
[Test]
public void NewsController_Index()
{
// Arrange
var news = new Mock<IEnumerable<News>>();
mockNewsRepository.Setup(r => r.FindAll()).Returns(news.Object).Verifiable();
// Act
ActionResult actual = newsController.Index();
// Assert
mockNewsRepository.Verify();
actual
.AssertViewRendered()
.ForView("Index")
.WithViewData<News[]>()
.ShouldBe(news);
}
}
My view:
public ActionResult Index()
{
FakeNewsRepository fakeNewsRepository = new FakeNewsRepository();
IEnumerable<News> news = fakeNewsRepository.FindAll();
return View(news);
}
I need some pointers on the way that I did it. Am I in the correct direction? What should I add, what should I leave out? I want to do unit testing, am I mixing it with integration testing? Any extra advice would be appreciated.
When I run this test in the NUnit GUI console then I get an error back and I'mnot sure what it means:
MyProject.Web.Tests.Controllers.NewsControllerTest.NewsController_Index:
Moq.MockVerificationException : The following setups were not matched:
INewsRepository r => r.FindAll()
public ActionResult Index()
{
FakeNewsRepository fakeNewsRepository = new FakeNewsRepository();
IEnumerable<News> news = fakeNewsRepository.FindAll();
return View(news);
}
You cannot mock the repository that is hardcoded like this in your action. You are instantiating it inside the action, you will never be able to unit test this and mock the repository. The repository needs to be injected as a dependency. You could use an interface and pass this interface to the constructor of your controller:
public class HomeController: Controller
{
private readonly IRepository _repository;
public class HomeController(IRepository repository)
{
_repository = repository;
}
public ActionResult Index()
{
IEnumerable<News> news = _repository.FindAll();
return View(news);
}
}
Now in your unit test you could pass the mocked instance of your repository to the controller constructor and define expectations.
Also notice that MVCContrib.TestHelper is designed to work with Rhino Mocks. I am not quite sure whether it works fine with Moq.
I have an action method like this in my controller
public ActionResult Index()
{
using (NorthwindDataContext db = new NorthwindDatacontext())
{
var results = db.GetRecordSets(arg1, ....).ToList();
// use results as list
}
return View();
}
and I wanted to start making tests for it (yes, after it was built, not before... but the code was written before I started to use TDD so... )
and I figured out that adding a property such as this one to the controller
public delegate NorthwindDatacontext ContextBuilderDelegate();
public ContextBuilderDelegate ContextBuilder { get; set; }
I could add in the constructor something like this...
ContextBuilder = () => new NorthwindDatacontext();
then I could test the ActionMethod setting the ContextBuilder property with a mock of NorthwindDatacontext
var controller = new MyController();
var mockDataContext = new Mock<NorthwindDatacontext>();
controller.ContextBuilder = () => mockDataContext.Object;
But... I found no way to use this because all methods of NorthwindDatacontext use ISingleResult as returnType and I cant find the way to create an object with that interface.
I've tried this
var theResult = new List<GetRecordSetsResult>();
// fill the data structure here with the provided result...
mockDataContext.Setup(c => c. GetRecordSets()).Returns(theResult as
ISingleResult<GetRecordSetsResult>);
but it doesn't work because theResult is null when converted to ISingleResult.
Is there any way to create a ISingleResult object to test this way or I'm doing the incorrect way to do things here?
Thanks in Advance
ToList() is an extension method for IEnumerable, which is easy to mock, because it only has one member method -- GetEnumerator().
Still you might have problems mocking NorthwindDataContext class, if its methods are not virtual...
Anyways, that's how I solved a similar problem in my sandbox, hope it helps:
public class MyType
{
public virtual ISingleResult<int> ReturnSomeResult() { throw new NotImplementedException(); }
}
[TestMethod]
public void TestMethod1()
{
var mockMyType = new Mock<MyType>();
var mockSingleResult = new Mock<ISingleResult<int>>();
IEnumerable<int> someEnumerable = new int[] {1,2,3,4,5};
mockSingleResult.Setup(result => result.GetEnumerator()).Returns(someEnumerable.GetEnumerator());
mockMyType.Setup(myType => myType.ReturnSomeResult()).Returns(mockSingleResult.Object);
Assert.AreEqual(15, mockMyType.Object.ReturnSomeResult().ToList().Sum());
}
I created a class that implemented ISingleResult and just put a List in it. I am fairly new to this type of coding, so while this worked for me, use at your own risk (and if you see holes post a comment).
class SingleResult<T>:ISingleResult<T>
{
readonly List<T> _list = new List<T>();
public void Add(T item)
{
_list.Add(item);
}
#region Interface Items
public IEnumerator<T> GetEnumerator()
{
return _list.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public object ReturnValue { get { return _list; } }
public void Dispose() { }
#endregion
}
This can then be used to return in part of a mock. This is how I ended up using it with Rhino Mocks:
[TestMethod]
public void TestSomething()
{
//Arrange
// Make a data context and DAL
var _ctx = MockRepository.GenerateMock<IDataClassesDataContext>();
var someDALClass = new SomeDALClass(_ctx);
User testUser = UserObjectHelper.TestUser();
SingleResult<User> userList = new SingleResult<User> { testUser };
// Indicate that we expect a call the to sproc GetUserByUserID
_ctx.Expect(x => x.GetUserByUserID(testUser.UserID)).Return(userList);
//Act
someDALClass.UpdateUser(testUser);
//Assert
Assert.IsTrue(SomeTestCondition());
}