Unit Tests - method of user controller - asp.net-mvc

I have a Controller named "UserController" with method named "Invite". My controller has the following override method:
DBRepository _repository;
protected override void Initialize(System.Web.Routing.RequestContext requestContext)
{
base.Initialize(requestContext);
_repository = new DBRepository();
}
so, this method is called each time when UserController class is created.
My method "Invite" has the following lines:
var startTime = _repository.Get<AllowedTime>(p => p.TimeID == selectTimeStart.Value);
but when I try to call this method via Unit method:
[TestMethod()]
[UrlToTest("http://localhost:6001/")]
public void InviteTest()
{
UserController target = new UserController(); // TODO: Initialize to an appropriate value
int? selectTimeStart = 57;
int? selectTimeEnd = 61;
Nullable<int> selectAttachToMeeting = new Nullable<int>(); // TODO: Initialize to an appropriate value
int InvitedUserID = 9; // TODO: Initialize to an appropriate value
UserInviteModel model = new UserInviteModel();
model.Comment = "BLA_BLA_BLA";
ActionResult expected = null; // TODO: Initialize to an appropriate value
ActionResult actual;
actual = target.Invite(selectTimeStart, selectTimeEnd, selectAttachToMeeting, InvitedUserID, model);
Assert.AreEqual(expected, actual);
Assert.Inconclusive("Verify the correctness of this test method.");
}
I got an error "Reference is not set...". I understand why it happens (_repository is null because Initialize method is not called in my case, but how to do it correctly?

If you expect DBRepository to actually perform the Get from your backing data store during your test, you could change your _repository field to be a Lazy<DBRepository>, that gets initialized upon first use. (I'm assuming it's being newed up in the Initialize method rather than the constructor because it relies on the current request context?)
If you want this to be a true unit test, it shouldn't test the DBRepository class at all: you should be programming to an interface that you can mock up. Additionally, you need to make it so that your DBRepository comes from someplace where it can be provided by the test case. You could have it built by a factory or provided as a singleton, and the test case could set up the factory or singleton to provide a mocked object ahead of time. However, the best approach would be to use Dependency Injection, so you can provide a fake/mock IDBRepository when you construct the new UserController().

Related

Setting Session on Specific Event Calls

I have an MVC application and a custom class called AuthorisationFilter which has a .NET interface of IAuthorizationFilter, this has an OnAuthorization method which gets called when I click around my site, at that point I go about validating the security access of the user (which works), but I don't want to do this all the time as it is time consuming.
In this I'm trying to use the Session to store a temporary piece of login information (this is an internal application by the way), but I can't get it working as I'd expect. I can't just use an HttpContext so end up constantly creating a new instance of HttpContextBase, which I assume is then clearing out the Session. My code is as follows:
internal void SetSecurityLevel(int token)
{
HttpContextBase _cBase = new HttpContextWrapper(HttpContext.Current);
_cBase.Session["SecurityRights"] = token;
}
internal int GetSecurityLevel()
{
HttpContextBase _cBase = new HttpContextWrapper(HttpContext.Current);
if (_cBase.Session["SecurityRights"] == null)
{
SetSecurityLevel(-1);
}
return (int)_cBase.Session["SecurityRights"];
}
Please note this is only part of the code, SetSecurityLevel is set to the correct value by a separate method call which is not shown
Anyway what I'm really wanting to do is have the session set in this class and have it persisted. I tried a few different ways, including setting the context when the class is initialised, but I end up with a NullReference on the .Session object in GetSecurityLevel
private HttpContextBase _cBase = new HttpContextWrapper(HttpContext.Current);
public AuthorisationFilter()
{
_cBase = new HttpContextWrapper(HttpContext.Current);
}
Is there a way I can do this within the class?
You are right that you can't set in the constructor but you can in OnActionExecuting when the context is available
public override void OnActionExecuting(ActionExecutedContext filterContext)
{
_session = = filterContext.HttpContext.Session;
I would wonder a little why you're setting this security level in the filter and not just doing it directly from where it's needed.

How to pass Interface as parameter for Controller class in Substitute

I am new to nSubstitute. And I am writing test method for my controller class. I have a TestMethod called GetDefaultStateTest() which having Substitute class as shown below
[TestMethod]
public void GetDefaultStateTest()
{
var _GetDefaultState = Substitute.For<CustomerController>(ICustomer cus);
Assert.IsNotNull(_GetDefaultState.GetDefaultState());
}
Because my controller class having parameterized constructor as below.
public class CustomerController : Controller
{
private readonly ICustomer _customer;
public CustomerController(ICustomer customer)
{
_customer = customer;
}
public string GetDefaultState()
{
// Get default state from settings table
List<tblSettings> settings = new List<tblSettings>();
// Calling service method GetSettings
settings = _customer.GetSettings();
var defaultState = from setting in settings
where setting.Desc == "DefaultState"
select setting.Settings;
string strState = "";
foreach (var oState in defaultState)
{
strState = oState;
break;
}
return strState;
}
}
While run the test method, it raise null reference issue. Because of parameter ICustomer is null
var _GetDefaultState = Substitute.For<CustomerController>(ICustomer cus);
How to resolve this problem.
If you are testing your controller class then you do not want to substitute for it, you want to use a real one (otherwise you'd just be testing a fake object "works" :)). Where you may want to substitute is for that class's dependencies, in this case, ICustomer.
[TestMethod]
public void GetDefaultStateTest()
{
var customer = Substitute.For<ICustomer>();
var controller = new CustomerController(customer);
Assert.IsNotNull(controller.GetDefaultState());
}
You may then want to fake out the ICustomer.GetSettings() method so you can test what your controller does with that data:
[TestMethod]
public void GetDefaultStateTestFromSettings()
{
var customer = Substitute.For<ICustomer>();
customer.GetSettings().Returns(somethingSensible);
var controller = new CustomerController(customer);
Assert.AreEqual(expectedDefaultState, controller.GetDefaultState());
}
As an aside, sometimes it makes more sense to use real objects (say, a real implementation of ICustomer) rather than substitutes. This will depend on how well-defined the interactions with the dependencies are, where you want to define the boundaries of your system under test, and how much confidence the test gives you that the system under test is working correctly. Or put more simply, whatever makes it easy and reliable to test. :)
Hope this helps.

Test if save method is hit in unit test

I'm starting with unit testing in the asp.net mvc 4 framework.
I got a repository with basic crud methods and a save method. When I create a unit test I create a test repository and test if e.g. a item to the collection is added. That all goes smoothly but I cannot test if the save method is hit.
I tried to add a boolean property to the test repository which will be set to true if .save() is hit. But then I need to change the interface, and also the database repository. Which is in my opinion neither practical nor best practice.
What is the best method to test this? Thank you in advance for your answer.
My code:
the fake repository:
public class TestUserRepository : IUserManagementRepository
{
/// <summary>
/// entries used used for testing
/// </summary>
private List<User> _entities;
/// <summary>
/// constructor
/// </summary>
public TestUserRepository()
{
_entities = new List<User>();
_entities.Add(new User
{
Id = 1,
InsertDate = DateTime.Now,
LastUpdate = DateTime.Now,
Username = "TestUserName",
Password = "TestPassword"
});
}
...
public void Create(User task)
{
_entities.Add(task);
}
public void Save()
{
//do nothing
}
}
the controller to test:
[HttpPost]
public ActionResult Create(User user)
{
if (ModelState.IsValid)
{
_repository.Create(user);
_repository.Save();
return RedirectToAction("Index");
}
else
{
return View(user);
}
}
and the test
[TestMethod()]
public void CreateTest()
{
IUserManagementRepository repository = new TestUserRepository();
UserController controller = new UserController(repository);
User user = new User { Username = "UnitTestUserName", InsertDate = DateTime.Now, LastUpdate = DateTime.Now, Password = "Password" };
ActionResult actionResult = controller.Create(user);
User returnedUser = repository.FindBy(u => u.Username == "UnitTestUserName").First<User>();
Assert.IsNotNull(actionResult);
Assert.AreEqual(user, returnedUser);
}
You must be careful not to write a bunch of unit tests that just test your test repository.
Consider the following scenario:
You have a service method, that is supposed to add an item to your repository.
Your unit test calls this method, and you should verify that the appropriate "AddX" method was called on the repository.
This is a valid unit test scenario, to test it you can use your test repository. Since it is your test object, you have full control over it. You can expose properties such as "AddXMethodCallCount" or something similar.
Over time you will find yourself writing a lot of test code that is pretty much boilerplate. The alternative, which I strongly recommend, is to use a mocking framework:
https://stackoverflow.com/questions/37359/what-c-sharp-mocking-framework-to-use
It takes some getting used to, but once you get it, it will speed up your unit testing significantly.
If you don't want to use mocking yet, but want to still achieve your goal of verifying whether or not Save() is called, I would suggest just adding a publicly exposed SaveMethodCallCount property:
public class TestUserRepository : IUserManagementRepository
{
...
public SaveMethodCallCount {get; set;}
...
public void Save()
{
SaveMethodCallCount++;
}
}
This works, because in your unit test you can actually say:
TestUserRepository repository = new TestUserRepository();
The UserController does not care, as long as the passed in parameter implements the IUserManagementRepository interface. The controller interacts with the repository object through the interface, but the unit test does not have to, and the TestUserRepository, being a test class, is allowed to have much more functionality, that does not have to be exposed through the interface.
So your test could look something like:
[TestMethod()]
public void CreateTest()
{
TestUserRepository repository = new TestUserRepository();
UserController controller = new UserController(repository);
User user = new User { Username = "UnitTestUserName", InsertDate = DateTime.Now, LastUpdate = DateTime.Now, Password = "Password" };
ActionResult actionResult = controller.Create(user);
User returnedUser = repository.FindBy(u => u.Username == "UnitTestUserName").First<User>();
Assert.IsNotNull(actionResult);
Assert.AreEqual(user, returnedUser);
Assert.AreEqual(1, repository.SaveMethodCallCount);
}
To make my example complete, let me show you what this would look like if you used a mocking framework, like Moq. You can see some more examples here. The example test method uses Moq and Arrange/Act/Assert, and tests only one thing - that Save() is called when Create() is called.
[TestMethod()]
public void Test_SaveCalledWhenCreateCalled()
{
// Arrange
// First, instead of creating an instance of your test class, you create a mock repository.
// In fact, you don't need to write any code, the mocking framework handles it.
var mockRepository = new Mock<IUserManagementRepository>();
// and pass the mock repository (which implements the IUserManagementRepository) to your controller
UserController controller = new UserController(mockRepository);
// Act
ActionResult actionResult = controller.Create(user);
// Assert
// see how easy it is to do with a mocking framework:
mockRepository.Verify(rep => rep.Save(), Times.AtLeastOnce());
}

Unit Test(mvc) -problem with Roles

I have mvc application and I'm working with poco objects and writing unit test. Problem is that all my test fail when they reach this line of code Roles.IsUserInRole("someUser", "role"). Should I implement new interface or repository for Roles or...?
Thx
I had the same problem when trying to mock the Roles.IsUserInRole functionality in my coded unit tests. My solution was to create a new class called RoleProvider and an interface with method IsUserInRole which then called the System.Web.Security.Roles.IsUserInRole:
public class RoleProvider: IRoleProvider
{
public bool IsUserInRole(IPrincipal userPrincipal)
{
return System.Web.Security.Roles.IsUserInRole(userPrincipal.Identity.Name, "User");
}
}
Then in my code I call the RoleProvider IsUserInRole method. As you have an interface you can then mock the IRoleProvider in your tests, example shown here is using Rhino Mocks:
var roleProvider = MockRepository.GenerateStub<IRoleProvider>();
roleProvider.Expect(rp => rp.IsUserInRole(userPrincipal)).Return(true);
Hope this helps.
You can set up a custom method to check roles that will behave differently in tests, but I prefer to have the tests set up a context that will work with the standard methods.
http://stephenwalther.com/blog/archive/2008/07/01/asp-net-mvc-tip-12-faking-the-controller-context.aspx
You could create a light wrapper with a Predicate/Func.
public static Predicate<string> IsUserInRole = role => Roles.IsUserInRole(role);
Then use IsUserInRole() instead of Roles.IsUserInRole(). At run time you get the same behavior. But at test time you can override the function so that it doesn't access the RoleProvider
MyClass.IsUserInRole = role => true;
If you prefer to not have a public static you could inject the Predicate via your constructor and store it as a private readonly.
class MyClass
{
private readonly Predicate<string> IsUserInRole;
MyClass(Predicate<string> roleChecker) { this.IsUserInRole = roleChecker }
MyClass() : this(role => Roles.IsUserInRole(role)) { }
}
If you use Moq you can return a mock and then control the return value and/or check the method was called. And check what parameter value was sent to the Predicate.
Mock<Predicate<string>> mockRoleChecker = new Mock<Predicate<string>>();
var cut = new MyClass(mockRoleChecker.Object);
var expectedRole = "Admin";
mockRoleChecker.SetReturnsDefault<bool>(true); // if not specified will return false which is default(bool)
cut.MyMethod();
mockRoleChecker.Verify(x => x(expectedRole), Times.Once());

How do I unit test my asp.net-mvc controller's OnActionExecuting method?

I've overridden my controller's OnActionExecuting method to set some internal state based on the executing filterContext. How do I test this? The method itself is protected so I assume I'll have to go higher up in the call stack.
What code do I need to test this?
I'm using mvc RC 1.
Edit: I'm also using nunit.
Thanks
You need to add and use a Private Accessor. Right click in your controller class and choose Create Private Accessors from the menu and add them to your test project. Once in your test project, create your controller, then create an accessor for it. The method should be available on the accessor. Here's a sample test from my own code:
/// <summary>
///A test for OnActionExecuting
///</summary>
[TestMethod()]
[ExpectedException( typeof( InvalidOperationException ) )]
public void OnActionExecutingWindowsIdentityTest()
{
var identity = WindowsIdentity.GetCurrent();
WindowsPrincipal principal = new WindowsPrincipal( identity );
var httpContext = MockRepository.GenerateStub<HttpContextBase>();
httpContext.User = principal;
var actionDescriptor = MockRepository.GenerateStub<ActionDescriptor>();
RouteData routeData = new RouteData();
BaseController controller = new BaseController();
BaseController_Accessor accessor = new BaseController_Accessor( new PrivateObject( controller ) );
ControllerContext controllerContext = MockRepository.GenerateStub<ControllerContext>( httpContext, routeData, controller );
ActionExecutingContext filterContext = new ActionExecutingContext( controllerContext, actionDescriptor, new Dictionary<string, object>() );
accessor.OnActionExecuting( filterContext );
}
EDIT: If you aren't using MSTest for your unit tests, you may have to generate the accessors by hand. Essentially, you make a wrapper class that exposes the private/protected methods of the class under test via equivalent public methods, pass an instance of the class under test to the wrapper, and then use reflection from the wrapper class to invoke the private/protected method on the class under test.
public class MyClass
{
protected void DoSomething( int num )
{
}
}
public class MyClass_accessor
{
private MyClass privateObj;
public MyClass_accessor( MyClass obj )
{
this.privateObj = obj;
}
public void DoSomething( int num )
{
MethodInfo info = privateObj.GetType()
.GetMethod("DoSomething",
BindingFlags.NonPublic
| BindingFlags.Instance );
info.Invoke(obj,new object[] { num });
}
}
I recently had a similar problem and could not find satisfying solution. So I created my own helper function that invokes OnActionExecuted and OnActionExecuting. See code here http://mkramar.blogspot.com.au/2012/06/onactionexecuting-and-onactionexecuted.html
I was trying to do this, but I actually wanted to test the outcome of the custom attribute as it applied to the actual controller. In our case we had an authorization attribute that set properties on the controller, the controller then used the properties. Our code looks something like this:
// Create the controller to test
PortalController controller = new PortalController();
var method = typeof(PortalController);
var attribute = method.GetCustomAttributes(typeof(OrganizationContextFilter),true).Cast<OrganizationContextFilter>().SingleOrDefault();
// Set the controller Context with our fake objects on it
controller.ControllerContext = this.GetDefaultControllerMock(controller);
// Execute the Organization Context Filter
var actionDescriptor = new Mock<ActionDescriptor>();
var context = Mock.Get(actionDescriptor.Object);
context.Setup(s => s.ControllerDescriptor).Returns(new Mock<ControllerDescriptor>().Object);
// Use the current controller Context
ActionExecutingContext filterContext = new ActionExecutingContext( controller.ControllerContext, actionDescriptor.Object, new Dictionary<string, object>() );
attribute.OnActionExecuting(filterContext);
// We have to use this one, because it has the result of the Attribute execution
PortalController pc = filterContext.Controller as PortalController;
ActionResult result = pc.MethodToTest(); // Call the controller that had OnActionExecuting results
The benefit of this is that we actually execute the custom MVC attribute on the controller we are actually testing. This both exercises the custom attribute code and tests the controller in a situation that is more like the "real world".

Resources