HttpContext Null through Unit testing - c#

I have following piece of code to evaluate the IP address
public string getIPAddress()
{
string IPAddress = string.Empty;
String strHostName = HttpContext.Current.Request.UserHostAddress.ToString();
IPAddress = System.Net.Dns.GetHostAddresses(strHostName).GetValue(0).ToString();
return IPAddress;
}
Now when I tried to implement unit testing for this method, it always throws error, null reference,
I could not change the actual method just for unit testing, is there any way to handle this...
Thanks

That is expected because HttpContext is not available in unit tests and unit tests run in their own context. You will need to have a way to mock/provide HttpContext to your unit tests.

if you would not use "HttpContext.Current.Request.UserHostAddress" direct - but through a wrapperclass or other mockable class instead, you could then mock the behaviour.
Here is an Example
you should probably mock System.Net.Dns.GetHostAddresses(strHostName).GetValue(0) as well, to get your Test independent of this Class too.

if you want to mock HTTPContext while unit testing you can use typemock as in the following example regarding you method:
[TestMethod,Isolated]
public void TestForHttpContext_willReturn123AsIP()
{
// Arrange
Program classUnderTest = new Program();
IPAddress[] a = { new IPAddress(long.Parse("123")), new IPAddress(long.Parse("456")), new IPAddress(long.Parse("789")) };
Isolate.WhenCalled(() => HttpContext.Current.Request.UserHostAddress).WillReturn("testIP");
Isolate.WhenCalled(() => Dns.GetHostAddresses(" ")).WillReturn(a);
// Act
var res = classUnderTest.getIPAddress();
// Assert
Assert.AreEqual("123.0.0.0", res);
}

Related

dotnet core web app unit test controller

I have a dotnetcore web app and am looking to unit test the controllers. How do I get about this?
I have a simple controller that looks like this
public class ConversionController : Controller {
private readonly INumberService _numberService;
public ConversionController(INumberService numberService)
{
this._numberService = numberService;
}
// GET http://localhost:9789/api/conversion/123
[HttpGet("{number}")]
public string Get(decimal number)
{
return _numberService.ConvertToWords(number);
}
}
The INumberService is passed in as a parameter. How do I unit test this?
By mocking the interface/dependency and exercising an isolated unit test for the Get method. You could either create your own mock or use a mocking framework to mock the dependency. From there assert that the system under test behaves as expected.
For example the following simple test uses Moq to mock the dependency and test the Get method.
[TestMethod]
public void ConversionController_Get_Should_Return_Five() {
//Arrange
var number = 5;
var expected = "five";
var mock = new Mock<INumberService>();
mock.Setup(_ => _.ConvertToWords(number)).Returns(expected);
var sut = new ConversionController(mock.Object);
//Act
var actual = sut.Get(number);
//Assert
Assert.AreEqual(expected, actual);
}
You should also take some time and check the documentation provided
Unit Testing in .NET Core

Correctly implement Unit Test

I'm practicing on writing unit tests for the first time, and I have some questions. I'll start of by explaining what I'm trying to test.
I would like to test a method which looks like this:
public bool IsAdmin(HubCallerContext hubCallerContext)
{
return hubCallerContext.User.IsInRole("admin");
}
The method is implemented in a class UserService, which is connected to a interface IUserService.
I'm trying to create 2 tests:
One with a HubCallerContext which is in the role of "admin" and will assert true.
One with a HubCallerContext which is in the role of "user" and will assert false.
I've created a new class library in my solution, where I've refrenced the project I'm testing. I've installed NUnit and Moq, and created a test class which looks like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ChatProj;
using NUnit.Framework;
using ChatProj.Controllers;
using Moq;
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
using ChatProj.DAL;
using ChatProj.Service_Layer;
using System.Threading.Tasks;
namespace ChatProj.Tests
{
[TestFixture]
public class Class1
{
[SetUp]
public void Setup()
{
}
[Test]
public void IsAdmin_CalledByAdmin_ReturnTrue()
{
UserService userService = new UserService();
bool result = userService.IsAdmin( ? );
Assert.IsTrue( result, "Something is wrong." );
}
[Test]
public void IsAdmin_CalledByUser_ReturnFalse()
{
UserService userService = new UserService();
bool result = userService.IsAdmin( ? );
Assert.IsFalse( result, "Something is wrong." );
}
}
}
Here I start to get confused. (I've marked the parameters of the IsAdmin calls with "?" because I'm not sure what to put there.)
I've read about mocks, stubs, fakes and dummies, but the definitions are to abstract for me to really grasp. I've found these definitions for example:
- Dummy objects are passed around but never actually used. Usually they are just used to fill parameter lists.
- Fake objects actually have working implementations, but usually take some shortcut which makes them not suitable for production (an in memory database is a good example).
- Stubs provide canned answers to calls made during the test, usually not responding at all to anything outside what's programmed in for the test. Stubs may also record information about calls, such as an email gateway stub that remembers the messages it 'sent', or maybe only how many messages it 'sent'.
- Mocks are objects pre-programmed with expectations which form a specification of the calls they are expected to receive.
As I've designed my test class, I would need some sort of substitution for my HubCallerContext. This is assuming I'm testing the "IsAdmin" method the right way.
So my questions are:
Am I testing the "IsAdmin" method in a good way?
How would I practically make the tests work? Do I use a mock, and in that case, could you show how I would implement that, or point me in the right direction? Here is how the HubCallerContext works for
refrence.
Assuming HubCallerContext is this one - https://github.com/SignalR/SignalR/blob/master/src/Microsoft.AspNet.SignalR.Core/Hubs/HubCallerContext.cs - then setting up the tests will be easy. You just want two mocks of IPrincipal, one of which returns true for the .IsInRole("admin") call and the other that returns false.wrap these two in mocks of IRequest.
The syntax will vary depending on the mocking framework used, but your tests will end up something like:
[Test]
public void IsAdmin_CalledByAdmin_ReturnTrue()
{
UserService userService = new UserService();
var principalMock = new Mock<IPrincipal>();
principalMock.Setup(x => x.IsInRole("admin")).Returns(true);
var requestMock = new Mock<IRequest>();
requestMock.Setup(x => x.User).Returns(principalMock.Object);
var result = userService.IsAdmin(new HubCallerContext(requestMock.Object, ""));
Assert.IsTrue( result, "Something is wrong." );
}
[Test]
public void IsAdmin_CalledByUser_ReturnFalse()
{
UserService userService = new UserService();
var principalMock = new Mock<IPrincipal>();
principalMock.Setup(x => x.IsInRole("admin")).Returns(false);
var requestMock = new Mock<IRequest>();
requestMock.Setup(x => x.User).Returns(principalMock.Object);
var result = userService.IsAdmin(new HubCallerContext(requestMock.Object, ""));
Assert.IsFalse( result, "Something is wrong." );
}
I haven't checked if the above compiles, but it is based on the syntax needed for Moq.
I think that it would be much easier for You to write these two unit tests if You would change the method under test a little (assuming it's not a part of legacy code).
If you define the method this way:
public bool IsAdmin(IPrincipal user)
{
return user.IsInRole("admin");
}
things would get pretty simple (btw. check the "Law of Demeter" ;)). You can pass in a mock object (since the user parameter is an interface - IPrincipal) returning true if the user should be in role "admin" and false otherwise.
The benefit of this solution is that You don't have to build a graph of mock objects and the arrange part of your test is pretty simple. Your tests could look somewhat like this:
[Test]
public void IsAdmin_CalledByAdminUser_ReturnTrue()
{
//Arrange
var principalMock = new Mock<IPrincipal>();
principalMock.Setup(x => x.IsInRole("admin")).Returns(true);
//Act
var userService = ...// create an instance of userService here
var result = userService.IsAdmin(principalMock);
//Assert
Assert.IsTrue(result);
}
[Test]
public void IsAdmin_CalledByNonAdminUser_ReturnFalse()
{
//Arrange
var principalMock = new Mock<IPrincipal>();
principalMock.Setup(x => x.IsInRole("admin")).Returns(false);
//Act
var userService = ...// create an instance of userService here
var result = userService.IsAdmin(principalMock);
//Assert
Assert.IsFalse(result);
}
I would recommend You to read this series of blog posts (I think it's pretty cool :)): http://www.daedtech.com/tag/unit-testing
You can get the list of roles and check for each roles using foreach.

Mocking a method to throw an exception (moq), but otherwise act like the mocked object?

I have a Transfer class, simplified it looks like this:
public class Transfer
{
public virtual IFileConnection source { get; set; }
public virtual IFileConnection destination { get; set; }
public virtual void GetFile(IFileConnection connection,
string remoteFilename, string localFilename)
{
connection.Get(remoteFilename, localFilename);
}
public virtual void PutFile(IFileConnection connection,
string localFilename, string remoteFilename)
{
connection.Get(remoteFilename, localFilename);
}
public virtual void TransferFiles(string sourceName, string destName)
{
source = internalConfig.GetFileConnection("source");
destination = internalConfig.GetFileConnection("destination");
var tempName = Path.GetTempFileName();
GetFile(source, sourceName, tempName);
PutFile(destination, tempName, destName);
}
}
The simplified version of the IFileConnection interface looks like this:
public interface IFileConnection
{
void Get(string remoteFileName, string localFileName);
void Put(string localFileName, string remoteFileName);
}
The real class is supposed to handle a System.IO.IOException that is thrown when the IFileConnection concrete classes loses connectivity with the remote, sending out emails and what not.
I would like to use Moq to create a Transfer class, and use it as my concrete Transfer class in all properties and methods, except when the GetFile method is invoked - then I want it to throw a System.IO.IOException and make sure the Transfer class handles it properly.
Am I using the right tool for the job? Am I going about this the right way? And how would I write the setup for that unit test for NUnit?
Here's how you can mock your FileConnection
Mock<IFileConnection> fileConnection = new Mock<IFileConnection>(
MockBehavior.Strict);
fileConnection.Setup(item => item.Get(It.IsAny<string>,It.IsAny<string>))
.Throws(new IOException());
Then instantiate your Transfer class and use the mock in your method call
Transfer transfer = new Transfer();
transfer.GetFile(fileConnection.Object, someRemoteFilename, someLocalFileName);
Update:
First of all you have to mock your dependencies only, not the class you are testing(Transfer class in this case). Stating those dependencies in your constructor make it easy to see what services your class needs to work. It also makes it possible to replace them with fakes when you are writing your unit tests. At the moment it's impossible to replace those properties with fakes.
Since you are setting those properties using another dependency, I would write it like this:
public class Transfer
{
public Transfer(IInternalConfig internalConfig)
{
source = internalConfig.GetFileConnection("source");
destination = internalConfig.GetFileConnection("destination");
}
//you should consider making these private or protected fields
public virtual IFileConnection source { get; set; }
public virtual IFileConnection destination { get; set; }
public virtual void GetFile(IFileConnection connection,
string remoteFilename, string localFilename)
{
connection.Get(remoteFilename, localFilename);
}
public virtual void PutFile(IFileConnection connection,
string localFilename, string remoteFilename)
{
connection.Get(remoteFilename, localFilename);
}
public virtual void TransferFiles(string sourceName, string destName)
{
var tempName = Path.GetTempFileName();
GetFile(source, sourceName, tempName);
PutFile(destination, tempName, destName);
}
}
This way you can mock internalConfig and make it return IFileConnection mocks that does what you want.
I think this is what you want, I already tested this code and works
The tools used are: (all these tools can be downloaded as Nuget packages)
http://fluentassertions.codeplex.com/
http://autofixture.codeplex.com/
http://code.google.com/p/moq/
https://nuget.org/packages/AutoFixture.AutoMoq
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var myInterface = fixture.Freeze<Mock<IFileConnection>>();
var sut = fixture.CreateAnonymous<Transfer>();
myInterface.Setup(x => x.Get(It.IsAny<string>(), It.IsAny<string>()))
.Throws<System.IO.IOException>();
sut.Invoking(x =>
x.TransferFiles(
myInterface.Object,
It.IsAny<string>(),
It.IsAny<string>()
))
.ShouldThrow<System.IO.IOException>();
Edited:
Let me explain:
When you write a test, you must know exactly what you want to test, this is called: "subject under test (SUT)", if my understanding is correctly, in this case your SUT is: Transfer
So with this in mind, you should not mock your SUT, if you substitute your SUT, then you wouldn't be actually testing the real code
When your SUT has external dependencies (very common) then you need to substitute them in order to test in isolation your SUT. When I say substitute I'm referring to use a mock, dummy, mock, etc depending on your needs
In this case your external dependency is IFileConnection so you need to create mock for this dependency and configure it to throw the exception, then just call your SUT real method and assert your method handles the exception as expected
var fixture = new Fixture().Customize(new AutoMoqCustomization());: This linie initializes a new Fixture object (Autofixture library), this object is used to create SUT's without having to explicitly have to worry about the constructor parameters, since they are created automatically or mocked, in this case using Moq
var myInterface = fixture.Freeze<Mock<IFileConnection>>();: This freezes the IFileConnection dependency. Freeze means that Autofixture will use always this dependency when asked, like a singleton for simplicity. But the interesting part is that we are creating a Mock of this dependency, you can use all the Moq methods, since this is a simple Moq object
var sut = fixture.CreateAnonymous<Transfer>();: Here AutoFixture is creating the SUT for us
myInterface.Setup(x => x.Get(It.IsAny<string>(), It.IsAny<string>())).Throws<System.IO.IOException>(); Here you are configuring the dependency to throw an exception whenever the Get method is called, the rest of the methods from this interface are not being configured, therefore if you try to access them you will get an unexpected exception
sut.Invoking(x => x.TransferFiles(myInterface.Object, It.IsAny<string>(), It.IsAny<string>())).ShouldThrow<System.IO.IOException>();: And finally, the time to test your SUT, this line uses the FluenAssertions library, and it just calls the TransferFiles real method from the SUT and as parameters it receives the mocked IFileConnection so whenever you call the IFileConnection.Get in the normal flow of your SUT TransferFiles method, the mocked object will be invoking throwing the configured exception and this is the time to assert that your SUT is handling correctly the exception, in this case, I am just assuring that the exception was thrown by using the ShouldThrow<System.IO.IOException>() (from the FluentAssertions library)
References recommended:
http://martinfowler.com/articles/mocksArentStubs.html
http://misko.hevery.com/code-reviewers-guide/
http://misko.hevery.com/presentations/
http://www.youtube.com/watch?v=wEhu57pih5w&feature=player_embedded
http://www.youtube.com/watch?v=RlfLCWKxHJ0&feature=player_embedded
This is how I managed to do what I was trying to do:
[Test]
public void TransferHandlesDisconnect()
{
// ... set up config here
var methodTester = new Mock<Transfer>(configInfo);
methodTester.CallBase = true;
methodTester
.Setup(m =>
m.GetFile(
It.IsAny<IFileConnection>(),
It.IsAny<string>(),
It.IsAny<string>()
))
.Throws<System.IO.IOException>();
methodTester.Object.TransferFiles("foo1", "foo2");
Assert.IsTrue(methodTester.Object.Status == TransferStatus.TransferInterrupted);
}
If there is a problem with this method, I would like to know; the other answers suggest I am doing this wrong, but this was exactly what I was trying to do.

How to create a stub with Moq

How do I creat a pure stub using Moq? With Rhino Mocks I did it like this:
[TestFixture]
public class UrlHelperAssetExtensionsTests
{
private HttpContextBase httpContextBaseStub;
private RequestContext requestContext;
private UrlHelper urlHelper;
private string stylesheetPath = "/Assets/Stylesheets/{0}";
[SetUp]
public void SetUp()
{
httpContextBaseStub = MockRepository.GenerateStub<HttpContextBase>();
requestContext = new RequestContext(httpContextBaseStub, new RouteData());
urlHelper = new UrlHelper(requestContext);
}
[Test]
public void PbeStylesheet_should_return_correct_path_of_stylesheet()
{
// Arrange
string expected = stylesheetPath.FormatWith("stylesheet.css");
// Act
string actual = urlHelper.PbeStylesheet();
// Assert
Assert.AreEqual(expected, actual);
}
}
How would I create a stub for MockRepository.GenerateStub<HttpContextBase>(); using Moq? Or should I just stay with Rhino Mocks?
Here is my suggestion for you:
Mock<HttpContextBase> mock = new Mock<HttpContextBase>();
mock.SetupAllProperties();
Then you have to do the setup.
For further informations see homepage of the MOQ project.
A bit late to the party here but there's still not a sufficient answer here in my opinion.
Moq doesn't have explicit stub and mock generation in the same way RhinoMocks does. Instead, all setup calls, e.g. mockObject.Setup(x => blah ...) create a stub.
However, if you want the same code be treated as a mock, you need to call mockObject.Verify(x => blah ...) to assert that the setup ran as you expected.
If you call mockObject.VerifyAll(), it will treat everything you have setup as mocks and this is unlikely to be the behaviour you wish, i.e. all stubs treated as mocks.
Instead, when setting up the mock use the mockObject.Setup(x => blah ...).Verifiable() method to mark the setup explicitly as a mock. Then call mockObject.Verify() - this then only asserts the setups that have been marked with Verifiable().
var mockHttpContext = new Mock<HttpContextBase>();

Problem with matching setup in Moq

I've been using Moq for the past week or so and haven't had any issues until today. I'm having a problem with getting VerifyAll() to properly match the setup of my mock.
I'm currently writing unit tests for my application's API. Here's how the application is structured:
API <==> Service <==> DAO <==> Database
With this in mind, I'm mocking the service object and then constructing an API object using the mocked service. I've written a number of unit tests already without problem up until now.
I have two instance variables like this:
private Api _api;
private Mock<IHibernateService> mockService;
I initialize these in a setup method:
[SetUp]
public void DoSetupTasks()
{
mockService = new Mock<IHibernateService>();
_api = new Api(mockService.Object);
}
Here is the unit test that is failing:
[Test]
public void TestSearchOnAllProperties()
{
mockService
.Setup(service => service.LoadAll(It.IsAny<Type>()))
.Returns(new DomainBase[0]);
var dmbs = _api.SearchOnAllProperties("search term", typeof(DomainBase));
mockService.VerifyAll();
}
The API's SearchOnAllProperties() method will subsequently make a call to the service's LoadAll() method (with some additional logic of course), so I want to verify that it's being called properly. To clarify, here's how LoadAll() is being called in SearchOnAllProperties():
public IEnumerable<DomainBase> SearchOnAllProperties(string searchTerm, Type type)
{
foreach (DomainBase dmb in _hibernateService.LoadAll(type))
{
// additional logic
}
}
However, when I run the unit test, I get a MockVerificationException stating that the given setup was not matched. I cannot figure out why as it should be calling the service's LoadAll() method.
One possible cause is that at some point before this particular test method is called, mockService is being assigned to a new instance of Mock<IHibernateService>. If that is the case, then this test method would be calling Setup on the wrong instance, which would then produce this exception.
A quick way to test this would be to use local mockService and api variables and see if the test still fails:
[Test]
public void TestSearchOnAllProperties()
{
var localMockService = new Mock<IHibernateService>();
var localApi = new Api(localMockService.Object);
localMockService
.Setup(service => service.LoadAll(It.IsAny<Type>()))
.Returns(new DomainBase[0]);
var dmbs = localApi.SearchOnAllProperties("search term", typeof(DomainBase));
localMockService.VerifyAll();
}
HTH

Categories

Resources