Mocking Request.UserHostAddress for Unit Testing for WEB API - c#

I am writing Unit Test for my WEB API Service. I want to mock request from ip address. I am using Microsoft Unit Test.
[TestClass]
public class UnitTest1
{
private Mock<HttpContextBase> moqContext;
private Mock<HttpRequestBase> moqRequest;
[TestMethod()]
public void TestMethod1()
{
var controller = new TestController();
controller.ControllerContext = new ControllerContext(moqContext.Object, new System.Web.Routing.RouteData(), controller);
}
[TestInitialize]
public void SetupTests()
{
// Setup Moq
moqContext = new Mock<HttpContextBase>();
moqRequest = new Mock<HttpRequestBase>();
moqContext.Setup(x => x.Request).Returns(moqRequest.Object);
moqContext.Setup(x => x.Request.UserHostAddress).Returns("192.111.1.1");
}
}
I don't know how to proceed further, I am getting below error.
> Severity Code Description Project File Line Suppression State
> Error CS1503 Argument 3: cannot convert from
> 'WebApplication1.Controllers.TestController' to
> 'System.Web.Mvc.ControllerBase' UnitTestProject1
Any help appreciated.
Is MOQ better than Rino, also, alternate ways for avoiding virtual methods for MOQ testing.
Updates
Ok so the Controller is an API Controller as follows
// GET: api/Test
public IEnumerable<string> Get()
{
string s =HttpContext.Current.Request.UserHostAddress;
...Authentication/Authorization based on IP address
return new string[] { s };
}
I want to mock HttpContext.Current.Request.UserHostAddress in my Unit test so as to test different IP address. My question is how to set the mock IP address. I have found a link https://blog.slatner.com/geeky/mocking-request-userhostaddress-in-asp-net-mvc.html. but I couldn't figure out how to use. Any help much appreciated.

Have you tried setting up the mock request object instead?
// moqContext.Setup(x => x.Request.UserHostAddress).Returns("192.111.1.1"); <-- not this
moqRequest.Setup(x => x.UserHostAddress).Returns("192.111.1.1")

It means that your TestControllerclass does not inherit from System.Web.Mvc.ControllerBase. So go back to the definition of your TestController and make sure it looks like
public class TestController: System.Web.Mvc.ControllerBase
{ /* your code here */ }

Related

Unable to load config in class library project in nunit unit test c# [duplicate]

I am working in an ASP.net MVC 5 application. I would like to Unit Test my controller action which looks like this
public ActionResult Search()
{
var vm = SetupSearchViewModel();
return View(vm);
}
All the hard work is done by the SetupSearchViewModel() method, which itself is an orchestrator calling many different other methods, one of which is this
private string ExtractJsonFile(string filename)
{
var filePath = HttpContext.Server.MapPath(filename);
var json = System.IO.File.ReadAllText(filePath);
return json;
}
I plan on doing many Unit Tests on this particular action, but I'm starting with a very simple Unit Test which checks that the correct type of ActionResult is returned
[Test]
public void Search_Get_ReturnsViewResult()
{
// arrange
var performanceController = PerformanceControllerInstance;
// act
var result = performanceController.Search();
//assert
Assert.IsNotNull(result as ViewResult);
}
The test is failing because of the ExtractJsonFile method. It uses HttpContext and that is null. I am using Rhino Mocks to do the mocking of the various classes.
What would be the best way to Unit Test this? Darin in this thread suggest we avoid HttpContext.Current if we want our code Unit Tested.
By the way I tried mocking the HttpContext and made it not null, but then the Server is null, I can go ahead and mock that too I suppose (I don't know how yet), but is there no better way? I've no problem doing major refactoring if needed.
HttpContext.Server.MapPath would require an underlying virtual directory provider which would not exist during the unit test. Abstract the path mapping behind a service that you can mock to make the code testable.
public interface IPathProvider {
string MapPath(string path);
}
In the implementation of the concrete service you can make your call to map the path and retrieve the file.
public class ServerPathProvider: IPathProvider {
public string MapPath(string path) {
return HttpContext.Current.Server.MapPath(path);
}
}
you would inject the abstraction into your controller or where needed and used
public MyController : Controller {
public MyController(IPathProvider pathProvider) {
this.pathProvider = pathProvider;
}
//...other code removed for brevity
private string ExtractJsonFile(string filename) {
var filePath = pathProvider.MapPath(filename);
var json = System.IO.File.ReadAllText(filePath);
return json;
}
}
Using your mocking framework of choice you can then mock the provider
[Test]
public void Search_Get_ReturnsViewResult() {
// arrange
IPathProvider mockedPathProvider = //...insert your mock/fake/stub here
var performanceController = PerformanceControllerInstance(mockedPathProvider);
// act
var result = performanceController.Search();
//assert
Assert.IsNotNull(result as ViewResult);
}
and not be coupled to HttpContext
You could even go further and refactor the entire ExtractJsonFile(string filename) into its own service to get around being tied to disk as well.
public interface IJsonProvider {
string ExtractJsonFile(string filename);
}
This service is now flexible enough to get the file from other sources like web service if needed.

Log4Net on a MVC web solution

I'm creating a solution that contains two projects: the web project ant it's test project. I'm using Log4net for logging purposes, CastleWindsor for dependency injection and moq for the tests.
The problem I have is the configuration of the test. I want to test the HomeController that is Logging to a file, but when I run the test I don't want to Log, I think is absurd.
Is there a way to skip Logging in the test project?
The HomeController class:
public class HomeController : Controller
{
// this is Castle.Core.Logging.ILogger, not log4net.Core.ILogger
public ILogger Logger { get; set; }
private IRowan _rowan;
public HomeController(IRowan rowan)
{
_rowan = rowan;
}
public ActionResult Index()
{
//In the [tests] Logger fails
Logger.Debug("GET Request traced");
Logger.Error("Example of Error");
String test = _rowan.DoSomething();
ViewBag.Title = test;
return View();
}
}
}
It's test:
[TestClass]
public class HomeControllerTest
{
private static WindsorContainer _container;
[ClassInitialize()]
public static void InstallWindsor()
{
_container = new WindsorContainer();
// configure other classes
}
[ClassCleanup()]
public static void DisposeContainer()
{
_container.Dispose();
}
[TestMethod]
public void Index()
{
// Disponer
var mock = new Mock<IRowan>();
mock.Setup(m => m.DoSomething()).Returns("Home Page");
HomeController controller = new HomeController(mock.Object);
// Actuar
ViewResult result = controller.Index() as ViewResult;
// Declarar
Assert.IsNotNull(result);
Assert.AreEqual("Home Page", result.ViewBag.Title);
}
}
If the answer is no, which is the best way to implement log4net for testing?
PD: When I run the code, It works fine. When I run the test, Logger throws an exception because is null.
PD: I'm starting using the Microsoft Technology.
You could mock your Logger and set it on your controller like so:
Mock<ILogger> mockLogger = new Mock<ILogger>();
controller.Logger = mockLogger.Object;
Note that you shouldn't really need to use CastleWindsor in your tests. That's useful for controlling the lifecycle of objects in your application but in your tests you should be injecting things by hand. You are actually doing this in the example above. From the code you've posted you can remove the ClassInitialize and ClassCleanup functions and it will run the same.
You can use an other config for your test project.
Read more: https://logging.apache.org/log4net/release/manual/configuration.html

How to add a hard coded value to an object in a class from unit test for testing purpose

[HttpGet]
public IHttpActionResult GetTerm()
{
Response resp = new Response();
resp = InfomationController.GetTermAndCond(); //line 'LI001'
return Ok(resp);
}
[TestMethod]
public void GetTerm_FromGetTerm()
{
var controller = new ServController();
IHttpActionResult actionResult = controller.GetTerm();
Assert.IsNotNull(actionResult);
}
In here above Response class act as a template that adds another field(massage) according to the values added to it by GetTermAndCond(); (static method).
I want to know how can I properly write a unit test to this when
there is a static method.
Is there any way that I can add a value to line 'LI001' from
the test method and check whether this gives the necessary response accordingly.
P.S.- The source code cannot be changed no matter what. I know this can be a duplicate for some perspective but I surf through stack so many times and didn't find a solution. So it will be a great help if some one can find an answer to this.
Generate a Fakes assembly for the assembly containing InformationController. Then you can re-write your unit-test method as so:
[TestMethod]
public void GetTerm_FromGetTerm()
{
var controller = new ServController();
using (ShimsContext.Create())
{
MyAssembly.Fakes.ShimInteractionController.GetTermsAndConds = () => SomeCannedResponse();
IHttpActionResult actionResult = controller.GetTerm();
var result = controller.GetTerm(); // Why do you call GetTerm twice?!
Assert.IsNotNull(actionResult);
}
}

HttpContext.Current is null when unit test

I have following web Api controller method.
When I run this code through web, HttpContext.Current is never null and give desired value.
public override void Post([FromBody]TestDTO model)
{
var request = HttpContext.Current.Request;
var testName = request.Headers.GetValues("OS Type")[0];
// more code
}
However, when I call this method from Unit Test, HttpContext.Current is always null.
How do i fix it?
During unit tests HttpContext is always null as it is usually populate by IIS. You have a few options around this.
Sure, you could mock the HttpContext, (which you shouldn't really do - Don't mock HttpContext!!!! He doesn't like to be mocked!),. You should really try to stay away from tight coupling with HttpContext all over your code. Try constraining it to one central area (SRP);
Instead figure out what is the functionality you would like to achieve and design an abstraction around that. This will allow for your code to be more testable as it is not so tightly coupled to HttpContext.
Based on your example you are looking to access header values. This is just an example of how to change your thinking when it comes to using HttpContext.
Your original example has this
var request = HttpContext.Current.Request;
var testName = request.Headers.GetValues("OS Type")[0];
When you are looking for something like this
var testName = myService.GetOsType();
Well then create a service that provides that
public interface IHeaderService {
string GetOsType();
}
which could have a concrete implementation like
public class MyHeaderService : IHeaderService {
public string GetOsType() {
var request = HttpContext.Current.Request;
var testName = request.Headers.GetValues("OS Type")[0];
return testName;
}
}
Now in your controller you can have your abstraction instead of having tight coupling to HttpContext
public class MyApiController : ApiController {
IHeaderService myservice;
public MyApiController(IHeaderService headers) {
myservice = headers;
}
public IHttpActionResult Post([FromBody]TestDTO model) {
var testName = myService.GetOsType();
// more code
}
}
You can later inject your concrete type to get the functionality you want.
For testing you then swap dependencies to run your test.
If the method under test is your Post() method you can create a fake dependency or use a mocking framework
[TestClass]
public class MyTestClass {
public class MyFakeHeaderService : IHeaderService {
string os;
public MyFakeHeaderService(string os) {
this.os = os;
}
public string GetOsType() {
return os;
}
}
[TestMethod]
public void TestPostMethod() {
//Arrange
IHeaderService headers = new MyFakeHeaderService("FAKE OS TYPE");
var sut = new MyApiController(headers);
var model = new TestDTO();
//Act
sut.Post(model);
//Assert
//.....
}
}
This is by design and it's always null. But there is a FakeHttpContext project on Nuget that simply you can use it.
To install FakeHttpContext, run the following command in the Package Manager Console (PMC)
Install-Package FakeHttpContext
And then use it like this:
using (new FakeHttpContext())
{
HttpContext.Current.Session["mySession"] = "This is a test";
}
Visit https://www.nuget.org/packages/FakeHttpContext to install the package
See examples on Github: https://github.com/vadimzozulya/FakeHttpContext#examples
Hope this will help :)
All you need is
controller.Request = new HttpRequestMessage();
controller.Configuration = new HttpConfiguration();
From unit-testing-controllers-in-web-api

unit testing structuremap provides an implementation

how can I write a unit test to test that asking for an interface does provide an implementation? I'm using NUnit together with StructureMap
Maybe something like this based on examples in the code? The problem I have is that I don't know how to setup the test.
Code snippet
[Test]
public void TestCustomerRegistration()
{
var res = ObjectFactory.GetInstance<ICustomer>();
Assert.IsNotNull(res, "Cannot get an Customer");
}
This is already present in the code
Not sure if I have to use a similar thing for my ICustomer test? Not sure what this is.
[TestFixtureSetUp]
public void SetUp()
{
ObjectFactory.Initialize(x =>
{
x.AddRegistry<InfrastructureRegistry>();
x.AddRegistry<RepositoryRegistry>();
});
var container = ObjectFactory.Container;
IDependencyResolver resolver = new SmDependencyResolver(container);
ObjectFactory.Configure(x =>
{
x.For<IDependencyResolver>().Use(resolver);
});
}
Take the folloing MVC controller
I need to write a test that StructureMap provides 'Customer' when the _customer.GetById(id) is called. Hope this helps
private ICustomer _customer;
public MyController(ICustomer customer)
{
_customer = customer;
}
public ActionResult GetCustomer(int id)
{
var result = _customer.GetById(id); // I need to test that _customer works
}
Thanks,
If you are writing useless tests for checking some configuration of StructureMap (which is used for unit-tests, not for real running application), then it's easy to do! Use Assert.IsInstanceOf<T> to check exact type of returned object. It should be type which you are expecting StructureMap configured to return for customer interface:
[Test]
public void TestCustomerRegistration()
{
var customer = ObjectFactory.GetInstance<ICustomer>();
Assert.IsNotNull(customer, "Cannot get an Customer");
Assert.IsInstanceOf<SpecificCustomerType>(customer, "Wrong customer type");
}
UPDATE you should test controller in isolation from other objects (otherwise you will not know source of failures) and your controller test should look like (Moq sample)
[Test]
public void ShouldReturnExistingCustomer()
{
// Arrange
int id = 42; // or random numer
var dto = // data which ICustomer should return
Mock<ICustomer> customerMock = new Mock<ICustomer>();
customerMock.Setup(c => c.GetById(id)).Returns(dto)
var controller = new MyController(customer.Object);
// Act
var result = controller.GetCustomer(id);
// Assert
customerMock.VerifyAll();
Assert.IsNotNull(result); // etc
}
This is a controller test and it verifies that controller works (and calls customer to get data). If you want to verify _customer works, then you should write customer tests.

Categories