ASP.NET MVC Unit Testing - Sessions - asp.net-mvc

Having searched StackOverflow, and Google I think what I'm doing is suppose to be right, however results don't seem to be going well
[TestMethod]
public void LoginAction_Should_Return_View_and_User_Authenticated()
{
// Arrange
var mock = new Mock<ControllerContext>();
var mockSession = new Mock<HttpSessionStateBase>();
mock.Setup(p => p.HttpContext.Session).Returns(mockSession.Object);
var testData = FakeUserData.CreateTestUsers();
var repository = new FakeUserRepository(testData);
var controller = new AccountController(repository);
controller.ControllerContext = mock.Object;
// Act
var result = controller.Login("testuser1", "testuser1");
// Assert
Assert.AreEqual("testuser1", controller.HttpContext.Session["Username"]);
Assert.IsTrue((bool)controller.HttpContext.Session["IsAuthenticated"]);
Assert.IsInstanceOfType(result, typeof(RedirectToRouteResult));
}
When I run the test the value of controller.HttpContext.Session["Username"] is null, however I set the value to the username using a Session helper. Am I doing something completely wrong, or something else? Any help would be greatly appreciated.

Use Mock.Verify to check if underlying code tried to set Session["Username"].
If your code needs to set session variable and use it - take a look here.
Quickstart is priceless too.

Related

elastic search setup in asp.net mvc

I am working on an asp.net application where I have huge database. I want to implement elastic search. Here is what I have done in code:
var node = new Uri("http://localhost:9200/");
var setting = new ConnectionSettings(node);
setting.DefaultIndex("businessuser");
client = new ElasticClient(setting);
CanadaBusinessDBEntities db = new CanadaBusinessDBEntities();
client.DeleteIndex("businessuser", null);
var ListofBusiness = db.CanadaTables.ToList();
foreach (var Business in ListofBusiness)
{
var resutl = client.Index(Business, null);
}
This code is written in constructor which gets all records and then index them using elastic search. indexing is taking long time. I want to ask if this is correct way? I am new to elastic search. please suggest better way to do this.
Thanks.
You have to use ElasticsearchContext Class of Nest.
private readonly ElasticsearchContext _elasticsearchContext;
private const string ConnectionString = "http://localhost:9200";
private readonly IElasticsearchMappingResolver _elasticsearchMappingResolver;
_elasticsearchMappingResolver = new ElasticsearchMappingResolver();
_elasticsearchContext = new ElasticsearchContext(ConnectionString, new ElasticsearchSerializerConfiguration(_elasticsearchMappingResolver,true,true));
for Delete purpose you can use like that below
public void DeleteSkill(int Id)
{
_elasticsearchContext.DeleteDocument<Tag>(Id);
_elasticsearchContext.SaveChanges();
}

How to pass Model value from Test class to Action Method in Controller class

I am creating some Nunit tests for an MVC application. I am writing a test case for a methods in my Controller class. I am using Nsubstitute for Mocking the object.
I am learning about Nunit and Nsubstitue and I don't know, how to pass my Model value which was mocked in the testcase method to my controller method.
Below is my method in the controller class:
public ActionResult Manage(string id)
{
var clusterCollections = ReadXml();
int clusterIndex = clusterCollections.ClusterCollectionList.FindIndex(a => a.ClusterId == id);
var model = new ClusterManagementModel()
{
ClusterNodeDetailsList = BindClusterDetailsToGrid(id),
DropDownListClusterName = BindClusterNameToDropDown(),
CurrentClusterId = clusterIndex,
CurrentClusterName = id,
HStatus = Hstatus(id),
IStatus = Istatus(id)
};
return View(model);
}
This is the TestCase I have written:
[TestCase]
public void TestManage()
{
var ManagementController = Substitute.ForPartsOf<ClusterManagementController>();
var ManagementModel = Substitute.ForPartsOf<ClusterManagementModel>();
ClusterCollections clusterCollection = new ClusterCollections();
List<ClusterNodeDetails> ClusterNodes = new List<ClusterNodeDetails>();
List<DDL_ClusterName> DropDownListClusterName = new List<DDL_ClusterName>();
ManagementController.ReadXml().Returns(clusterCollection);
ManagementModel = new ClusterManagementModel()
{
ClusterNodeDetailsList = ClusterNodes,
DropDownListClusterName = DropDownListClusterName,
CurrentClusterId = 1,
CurrentClusterName = "UnitTesting",
HStatus = "True",
IStatus = "Success"
};
var result = ManagementController.Manage("1") as ActionResult;
Assert.AreEqual(ManagementModel, result);
}
If I have made mistakes in the TestCase Method please correct me.
If my TestCase is wrong, can you give me a suggestion how to write a TestCase for the above method (public ActionResult Manage(string id))
I don't know, how to pass Model value
The short answer is that in its current form, you can't pass the model you've created in your test to your controller. This is a common problem that people run into when they first start trying to unit test their code. The way out of the hole is to start writing your production code with testing in mind.
One approach that is common is to extract dependencies from your class and to inject these dependencies through the constructor for the class. So, you might extract your model creation logic into a ModelFactory and modify your controller to have a constructor like this:
public ManagementController(IModelFactory modelFactory) {
_modelFactory = modelFactory;
}
There are various libraries that can help to inject these dependencies (Ninject, AutoFac etc). But if you don't want to / can't use them, then you will also need to add a default constructor that sets up your dependencies to default concrete implementations:
public ManagementController() {
_modelFactory = new ModelFactory();
}
This allows you to create Stubbed / Mocked / Substituted implementations of IModelFactory and inject it into your controller / other class under test. So, your test might start off something like this:
List<ClusterNodeDetails> ClusterNodes = new List<ClusterNodeDetails>();
List<DDL_ClusterName> DropDownListClusterName = new List<DDL_ClusterName>();
var model = new ClusterManagementModel()
{
ClusterNodeDetailsList = ClusterNodes,
DropDownListClusterName = DropDownListClusterName,
CurrentClusterId = 1,
CurrentClusterName = "UnitTesting",
HStatus = "True",
IStatus = "Success"
};
var modelFactory = Substitute.For<IModelFactory>();
modelFactory.CreateClusterManagementModel( /* args for model creation */).Returns(model);
var sut = new ManagementController(modelFactory);
var result = sut.Manage("1") as ActionResult;
You also need to think about what it is you're trying to test. By extracting the dependencies you're able to focus on the logic in your controller and focus your tests on that logic. It's very easy when you start using Mocks to get into a situation where you're not actually testing anything at all, other than whether or not you've set your Mocks up correctly. Remember, they are there to help you reproduce specific scenarios you need to force your production code to follow a particular flow, not to replace the logic contained in your production code.

Unit Testing MVC Controllers

A controller in my ASP.NET MVC application pre-populates form data displayed by my view according to a couple of fairly straight forward rules.
It seems like this would be a good thing to cover in my unit testing. But the only way I could see to verify the correct data is placed in the form, would be to extract the logic from the controller in what feels like an unnatural way.
Can someone suggest ways to approach this?
All the examples I've found of unit testing controllers seemed very trivial, such as verifying it returned the expected type of view. I'm not sure I even see the value in that.
You can test by casting the returned object to the appropriate class, instead of using their base class (which is returned by default)
For example, to test the default AccountController you'd so something like this:
var controller = new AccountController();
var result = controller.LogOn() as ViewResult;
var model = result.Model as LogOnModel;
Assert.IsTrue(model.RememberMe); // assuming you "pre-populated" enabled the checkbox
Checking if the returned object is filled with the right data does not seem "unnatural" to me, or did you meant it differently?
I would agree that testing the type of view returned would be somewhat pointless. However, testing that the expected "view" was returned along with its correct data would be a valid test case IMO.
For example here is a singular edit test case for an edit controller. Note, that this example is making use of Moq and Nunit but that aside it's fairly straight forward.
Note, that that ViewResult is cast to the expected view model and the assertions are then made against the expected contact.
Test:
[Test]
public void Edit_Get_Should_Lookup_Contact_From_Repository_And_Return_Edit_View()
{
// arrange
var _repository = new Mock<IContactRepository>();
var expectedContact = new Contact
{
First = "first",
Last = "last",
Email = "mail#test.com"
};
var mockContext = new Mock<ControllerContext>();
_repository.Setup(x => x.GetById(It.IsAny<int>())).Returns(expectedContact);
var controller = new ContactController(_repository.Object)
{
ControllerContext = mockContext.Object
};
// act
var result = controller.Edit(1) as ViewResult;
var resultData = (Contact)result.ViewData.Model;
// assert
Assert.AreEqual("Edit", result.ViewName);
Assert.AreEqual(expectedContact.First, resultData.First);
Assert.AreEqual(expectedContact.Last, resultData.Last);
Assert.AreEqual(expectedContact.Email, resultData.Email);
}
Controller:
[HttpGet]
public ActionResult Edit(int id)
{
var contact = _repository.GetById(id);
return View("Edit", contact);
}

Testing the User.IsInRole in MVC.NET

I am trying to test the User.IsInRole("Administrator") in my application, and actually trying to assign the User Role to ("Administrator") so that my test will pass. I am using Scott Hanselman's MvcMockHelpers to do this, and at the moment I have the following test.
[Test]
public void Create_CanInsertNewArticleView_IsNotNull()
{
// Arrange
var controller = new ArticleController();
MockRepository mockRepo = new MockRepository();
var fakeContext = MvcMockHelpers.FakeHttpContext(mockRepo, "~/Article/Create");
fakeContext.User.IsInRole("Administrator");
// Act
Article fakeArticle = FakeObjects.ReturnFakeArticle();
var result = controller.Create(fakeArticle) as ViewResult;
// Assert
Assert.IsNotNull(result);
}
However the actual controller's User is null at the moment.
Can anyone help me out and tell me what the correct test should be, to User.IsInRole("Administrator")
Thanks for your help and time
Johann
See this related answer for details.
Here's the code snippet from the other answer converted to Rhino Mocks:
var user = new GenericPrincipal(new GenericIdentity(string.Empty), null);
var httpCtx = MockRepository.GenerateStub<HttpContextBase>();
httpCtx.User = user;
var controllerCtx = new ControllerContext();
controllerCtx.HttpContext = httpCtx;
sut.ControllerContext = controllerCtx;
You'll have to mock an IPrincipal for your user object, set it up so that .IsInRole("Administrator") returns true, and then set your fakeContext up to return that IPrincipal for the.User property. It would be something like this:
EDIT: It turns out the OP is using Rhino Mocks, and the code I provided was for Moq. Here's an attempt att writing Rhino code, although I have never actually used Rhino myself. The original Moq code can be found below.
In Rhino Mocks, you'll want to add another helper method, or change the current one, so you have the following:
public static HttpContextBase FakeHttpContext(this MockRepository mocks, string url, IPrincipal user)
{
// Do the same setup as Scott does...
// ...and add this:
SetupResult.For(context.User).Return(user);
mocks.Replay(context);
return context,
}
Then you declare and set up your IPrincipal mock object like this before the call to FakeHttpContext, and send the mock object in as the third parameter.
In Moq:
fakeContext = MvcMockHelpers.FakeHttpContext("~/Article/Create");
fakeUser = new Mock<IPrincipal>();
fakeUser.Expect(usr => usr.IsInRole(It.IsAny<String>())).Returns(true);
fakeContext.Expect(context => context.User).Returns(fakeUser.Object);
(Disclaimer: It was a while since I wrote a unit test, and this code has not been tested even for compilation errors. Hence, there might be some wrinkles that need to be ironed out before you can use this code, but you get the general idea...)

ASP.NET MVC: Mock controller.Url.Action

Urls for menus in my ASP.NET MVC apps are generated from controller/actions. So, they call
controller.Url.Action(action, controller)
Now, how do I make this work in unit tests?
I use MVCContrib successfully with
var controller = new TestControllerBuilder().CreateController<OrdersController>();
but whatever I try to do with it I get controller.Url.Action(action, controller) failing with NullReferenceException because Url == null.
Update: it's not about how to intercept HttpContext. I did this in several ways, using MVCContrib, Scott Hanselman's example of faking, and also the one from http://stephenwalther.com/blog/archive/2008/07/01/asp-net-mvc-tip-12-faking-the-controller-context.aspx. This doesn't help me because I need to know WHAT values to fake... is it ApplicationPath? How do I set it up? Does it need to match the called controller/action? That is, how do Url.Action works and how do I satisfy it?
Also, I know I can do IUrlActionAbstraction and go with it... but I'm not sure I want to do this. After all, I have MVCContrib/Mock full power and why do I need another abstraction.
A cleaner way to do this is just use Moq(or any other framework you like) to Mock UrlHelper itself
var controller = new OrdersController();
var UrlHelperMock = new Mock<UrlHelper>();
controller.Url = UrlHelperMock.Object;
UrlHelperMock.Setup(x => x.Action("Action", "Controller", new {parem = "test"})).Returns("testUrl");
var url = controller.Url.Action("Action", "Controller", new {parem = "test"});
assert.areEqual("/Controller/Action/?parem=test",url);
clean and simple.
Here's how you could mock UrlHelper using MvcContrib's TestControllerBuilder:
var routes = new RouteCollection();
MvcApplication.RegisterRoutes(routes);
HomeController controller = CreateController<HomeController>();
controller.HttpContext.Response
.Stub(x => x.ApplyAppPathModifier("/Home/About"))
.Return("/Home/About");
controller.Url = new UrlHelper(
new RequestContext(
controller.HttpContext, new RouteData()
),
routes
);
var url = controller.Url.Action("About", "Home");
Assert.IsFalse(string.IsNullOrEmpty(url));
If you're using Moq (and not MvcContrib's TestControllerBuilder), you can mock out the context, similar to #DarianDimitrov's answer:
var controller = new OrdersController();
var context = new Mock<System.Web.HttpContextBase>().Object;
controller.Url = new UrlHelper(
new RequestContext(context, new RouteData()),
new RouteCollection()
);
This doesn't set the controller.HttpContext property, but it does allow Url.Action to execute (and return an empty string -- no mocking required).
Fake it easy works nicely:
var fakeUrlHelper = A.Fake<UrlHelper>();
controller.Url = fakeUrlHelper;
A.CallTo(() => fakeUrlHelper.Action(A<string>.Ignored, A<string>.Ignored))
.Returns("/Action/Controller");
Here is another way to solve the problem with NSubstitute. Hope, it helps someone.
// _accountController is the controller that we try to test
var urlHelper = Substitute.For<UrlHelper>();
urlHelper.Action(Arg.Any<string>(), Arg.Any<object>()).Returns("/test_Controller/test_action");
var context = Substitute.For<HttpContextBase>();
_accountController.Url = urlHelper;
_accountController.ControllerContext = new ControllerContext(context, new RouteData(), _accountController);

Resources