I've implemented ninject in a mvc project and this works as expected now I'm wanting to unit test, but can't seem to get it to work:
controller:
private IDependencyResolver _resolver;
public HomeController(IDependencyResolver resolver)
{
_resolver = resolver;
}
public ActionResult Index()
{
var model = _resolver.GetService<ISignUpViewModel>();
return PartialView("Login", model);
}
Unit Test
private IDependencyResolver _resolverMock;
[TestMethod]
public void SignUpTest()
{
var ctrl = new HomeController(_resolverMock);
var signUpMock = new Mock<ISignUpViewModel>();
ctrl.Index();
ctrl.ViewData.Model = signUpMock;
//Assert.AreEqual("", "");
}
The resolver is always null.
Ive looked at Ninject.MockingKernel.Moq should I set the resolver in there?
Any idea where I'm going wrong?
Thanks
In the unit test you manually create HomeController instance, So you need mock IDependencyResolver. For example:
var resolverMock = new Mock<IDependencyResolver>();
var ctrl = new HomeController(resolverMock.Object);
....
Related
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'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
I am trying to get my feet wet with asp.net mvc3 and unit testing.
I have created a model which uses the repository pattern. Here's the interface:
public interface IExtensionRepository
{
IList<Extensions> ListAll();
}
Here's the repository:
public class ExtensionRepository : IExtensionRepository
{
private ExtensionsLSDataContext _dataContext;
public ExtensionRepository()
{
_dataContext = new ExtensionsLSDataContext();
}
public IList<Extensions> ListAll()
{
var extensions = from ext in _dataContext.Extensions
select ext;
return extensions.ToList();
}
}
Here's the controller:
public class ExtensionController : Controller
{
private IExtensionRepository _repository;
public ExtensionController()
: this(new ExtensionRepository())
{
}
public ExtensionController(IExtensionRepository repository)
{
_repository = repository;
}
}
The pages seem to function as designed. Things go astray with my unit test, however. It resides in another project in the same solution. I am using Moq and NUnit. Here's my test:
[Test]
public void Test_Extension_Index_Views()
{
Mock<Extensions> extension = new Mock<Extensions>();
List<Extensions> extList = new List<Extensions>();
extension.Object.Extension = "5307";
extension.Object.Extension_ID = 1;
extension.Object.ExtensionGroup_ID = 1;
extList.Add(extension.Object);
Mock<IExtensionRepository> repos = new Mock<IExtensionRepository>();
repos.Setup(er => er.ListAll()).Returns(extList);
var controller = new ExtensionController(repos);
var result = controller.Index() as ViewResult;
Assert.AreEqual("Index", result.ViewName);
}
I am getting the following errors for the line that begins "var controller...":
The best overloaded method match for
'MvcApplication1.Controllers.ExtensionController.ExtensionController(MvcApplication1.Models.IExtensionRepository)'
has some invalid arguments
And:
Argument 1: cannot convert from
'Moq.Mock'
to
'MvcApplication1.Models.IExtensionRepository'
I know I've missed the boat somewhere, but I haven't a clue as to where... any ideas?
Change this:
var controller = new ExtensionController(repos);
to this:
var controller = new ExtensionController(repos.Object);
PS.: I know it sucks, but that's the way Moq was designed.
There is a simple controller that a querystring is read in constructor of it.
public class ProductController : Controller
{
parivate string productName;
public ProductController()
{
productName = Request.QueryString["productname"];
}
public ActionResult Index()
{
ViewData["Message"] = productName;
return View();
}
}
Also I have a function in unit test that create an instance of this Controller and I fill the querystring by a Mock object like below.
[TestClass]
public class ProductControllerTest
{
[TestMethod]
public void test()
{
// Arrange
var querystring = new System.Collections.Specialized.NameValueCollection { { "productname", "sampleproduct"} };
var mock = new Mock<ControllerContext>();
mock.SetupGet(p => p.HttpContext.Request.QueryString).Returns(querystring);
var controller = new ProductController();
controller.ControllerContext = mock.Object;
// Act
var result = controller.Index() as ViewResult;
// Assert
Assert.AreEqual("Index", result.ViewName);
}
}
Unfortunately Request.QueryString["productname"] is null in constructor of ProductController when I run test unit.
Is ther any way to fill a querystrin by a mocking and get it in constructor of a control?
There is a simple controller that a querystring is read in constructor of it.
You shouldn't be doing this and such controller shouldn't exist. The controller context is not yet initialized in the constructor and it will fail not only for the unit test but in real.
You should use the Initialize method where you have access to the request context.
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.