Request.Querystring is null when use unit test - asp.net

I want to create Nunit test case for ASP.NET MVC application. If the ASP.NET uses Request.QueryString or Request.Url. then the unit test case will return null reference exception since the Request.querystring will return the value if the control comes from UI only.
So can you please help on this to create a unit test for MVC controller which uses Httpcontext.Request attributes.

Your unit test runs outside of the HttpContext and therefore you either need to mock the HttpContext or change your architecture to work around the problem, an example of this is shown below:
http://volaresystems.com/Blog/post/Dont-mock-HttpContext.aspx

Related

Controller.User is Null During Unit Test

I have the following code in my controller action method:
if (User.Identity.IsAuthenticated)
{
// ...
}
It seems to work fine. But when I run a unit test that calls this action, it fails because User is null?
Can anyone suggest the best way to deal with this? Do I have to restructure this code just for unit tests?
You probably need to set the User property as part of your setup. You would do this by mocking the HttpContextBase via ControllerContext used to create the controller so that it returns your mocked user. Set your mocked ControllerContext into the ControllerContext property, and it will find User provided you've configured the object graph correctly.
The User property of the Controller class is copied from the current HttpContext - you have to provide a context and set the User there appropriately for this to work in your unit tests.
User will be null if you run the code outside of the context of a web request. It sounds like you're running tests on your methods directly.
You have two options.
The quickest fix to your problem, but not necessarily the most sustainable fix, would be to simply call your running website from your unit test as a WebRequest.
The more sustainable fix would be to gather your uses of context-dependent server-side functionality (such as User) into a single class that you can mock/fake.
Edit
Can anyone suggest the best way to deal with this? Do I have to restructure this code just for unit tests?
The bottom line answer is "yes". More importantly, you probably want to, because it will make your system more flexible and/or maintainable in the long run.

How set HttpContext.Current.User.Identity.Name for Unit Testing

Background:
I'm testing a function within an ASP.NET 4.0 (Web Forms not MVC) and I'm using Unit Testing built into Visual Studio 2010. I've created a separate test project and creating a test class for each class in the web project.
Question:
I've run into an issue with one of the functions that uses HttpContext.Current.User.Identity.Name as part of the logic. How do set that value in the Unit testing project class or method so that I can test that function?
Update:
What I was hoping for was that there was additional attribute I could set above my test method. Currently I have:
[TestMethod()]
[HostType("ASP.NET")]
[AspNetDevelopmentServerHost("C:\\DEV\\ProjectName\\ClientWeb", "/")]
[UrlToTest("http://localhost:9018/")]
public void GetLoginTest()
{
// test code
}
You ask the wrong question. HttpContext.Current.User.Identity is a dependency you should encapsulate before you can unit test your code. If encapsulated (probably behind an Interface) you can replace the abstraction with your test data / object.
You could create your own Principal by implementing IPrincipal, within that you'd need to define a custom Identity using the IIdentity interface, inside which you'd return your value for the Name property.
You could then set HttpContext.Current.User to your custom Principal object.

Unit Test Friendly way of using membership details inside the controller

Here is a piece of code from one of the controller inside my ASP.NET MVC 3 App :
_destinationdetailRepository.Add(new DestinationDetail {
DestinationID = destination.DestinationID,
CreatedOn = DateTime.Now,
CreatedBy = User.Identity.Name
});
What is important here is the CreatedBy property value which is User.Identity.Name. It works great and I use this on another parts of my app as well. But, I guess this is not a unit test firendly way of doing things.
So, what is the way of using Membership data inside the controller so that I will be happy when I am unit testing my app.
But, I guess this is not a unit test firendly way of doing things.
No, it's unit test friendly and it is correct code. The User property is an IPrincipal interface that can be mocked in an unit test.

Test presenter in ASP.NET Web Form

I am working on an ASP.NET WebForm application using MVP pattern. For every Web Form, there is a Presenter class associated to handle UI and Business logic. However, I had problem when writing unit tests for Presenters, since session values are used in presenters. And there is no HTTP context exists during execution of the unit test ( BTW I use nUnit ), making it is impossible to write unit test for presenters.
Anyone can explain how to unit test these presenters?
Thanks
you can either mock or stub out an IHttpContext and let your framework inject the real HttpContext or you can wrap the session, cookie, ... state behind some interfacing, or you could use "Moles" from Pex, the interfacing is explained here http://haacked.com/archive/2007/09/09/ihttpcontext-and-other-interfaces-for-your-duck-typing-benefit.aspx
You can change your Presenter class to have a dependency on HttpContextBase. Once that is done, you can supply a mocked version of the HttpContext to your presenter class for testing. In production, you would simply supply the HttpContext.Current property.
Hm, I would suggest another approach.
I think your presenter should not be aware of HttpContext, PageLifeCycle etc. because you have to test it in isolation. So rather than trying to mock IHttpContext, try to extract values that you need in presenter(you don't need whole httpcontext object right, just some values from session, cookies etc) and inject in presenter through presenter constructor. Now you can test it properly.
Cheers

How to unit test server controls on postback?

I am trying to create my own EasyBinderDropDown that currently looks like this:
public class EasyBinderDropDown : DropDownList, ICanBindToObjectsKeyValuePair {
public void BindToProperties<TYPE_TO_BIND_TO>(IEnumerable<TYPE_TO_BIND_TO>
bindableEnumerable,
Expression<Func<TYPE_TO_BIND_TO, object>> textProperty,
Expression<Func<TYPE_TO_BIND_TO, object>> valueProperty) {...}
public bool ShowSelectionPrompt { get; set; }
public string SelectionPromptText { get; set; }
public string SelectionPromptValue { get; set; }
//...
}
Basically it is very helpful for easy binding to objects from inside code since you just do something like _dropDown.BindToProperties(myCustomers, c=>c.Name, c=>c.Id) and it works for you, also by setting ShowSelectionPrompt and SelectionPromptText I can easily have a "Select Customer" Line. I don't want to ask so much about my specific implementation, rather I am confused how to write unit tests for some scenarios.
For example my current tests cover the control being created properly during load and having its output render properly but I am lost as to how to test what happens when the control gets posted back. Can anyone give me some advice on how to test that? I would prefer to do this without having to mock an HTTPContext or anything like that, Is there a way I can simulate the control being rebuilt?
"I would prefer to do this without having to mock an HTTPContext or anything like that, Is there a way I can simulate the control being rebuilt."
By definition, you are not asking to "unit test"; you are looking for an "integration test". If you are not mocking the major dependencies, in this case, the ASP.NET runtime components, the what you are testing is the integration between your control and ASP.NET.
If you do not want to mock out the HttpContext and friends, then I would suggest an automated web testing framework such as Selenium or NUnitAsp.
Update: Based on the comment. Don't have the code access directly the IsPostback or other asp.net stuff. Wrap them with simple classes/interfaces. Once you have done that, send mocks that implement those interfaces. This way you don't have to mock the whole HttpContext, just the pieces that matter for the code (which are really clear based on the interfaces involved).
Also, given it is an asp.net custom control, you don't want to force requirements on external things like dependency injection. Have a default (no parameters) constructor, that sets up the control to use the asp.net stuff. Use a constructor with more parameters to send the mocked versions.
Initial answer:
It seems to me you are looking for a happy middle between unit tests and integration tests. You are working with a custom control, which can go wrong on different parts of the asp.net's page lifecycle.
I would:
Check if you can move parts of the code
out of the custom control to separate
classes, you can more easily unit test
For simple scenarios, rely on the functional tests of the rest of the project to catch any further issue with the control (use watin / selenium rc).
For more complex scenarios, as if the control will be used in different parallel projects or will be delivered to the public, set up some test pages and automate against it (again watin / selenium rc).
You write the tests in watin / selenium rc in c#, and run them in your "unit" test framework. Make sure to keep them separated from the unit tests, since they will clearly run slower.
Ps. I haven't used ms test support for asp.net, it might have some support for what you are looking for.

Resources