How can I mock Elmah's ErrorSignal routine? - c#

We're using ELMAH for handling errors in our ASP.Net MVC c# application and in our caught exceptions, we're doing something like this:
ErrorSignal.FromCurrentContext().Raise(exception);
but when I try to unit test the caught exceptions, I get this message:
System.ArgumentNullException: Value cannot be null.
Parameter name: context
How can I mock the FromCurrentContext() call?
Is there something else I should be doing instead?
FYI... We're currently using Moq and RhinoMocks.
Thanks!

Since the FromCurrentContext() method is a static method you can't simply mock the call to it. You do have two other options.
Since FromCurrentContext() internally makes a call to HttpContext.Current you can push a fake context in that. For example:
SimpleWorkerRequest request = new SimpleWorkerRequest(
"/blah", #"c:\inetpub\wwwroot\blah", "blah.html", null, new StringWriter());
HttpContext.Current= new HttpContext(request);
With this it should not throw the exception anymore since HttpContext.Current is not null.
Create a wrapper class around the call to Raise and just mock out the wrapper class.
public class ErrorSignaler {
public virtual void SignalFromCurrentContext(Exception e) {
if (HttpContext.Current != null)
Elmah.ErrorSignal.FromCurrentContext().Raise(e);
}
}

Related

Setting up HttpContext for .Net Unit Tests

I'm writing an unit test(using NUnit & MOQ) for an action method MethodUnderTest which uses HttpContext internally to do some functionality. I'm setting up a fake hosting environment by calling InitializeHostingEnvironment where I'm initializing the session like:
public static HttpSessionState InitializeSession()
{
var httpRequest = new HttpRequest("", "http://localhost/", "");
var stringWriter = new StringWriter();
var httpResponse = new HttpResponse(stringWriter);
var httpContext = new HttpContext(httpRequest, httpResponse);
HttpContext.Current = httpContext;
HttpContext.Current.Items.Clear();
HttpSessionState session = (HttpSessionState)ReflectionHelper.Instantiate(typeof(HttpSessionState), new Type[] { typeof(IHttpSessionState) }, new FakeHttpSessionState());
HttpContext.Current.Items.Add("AspSession", session);
return session;
}
public static void InitializeHostingEnvironment(string userName, string password)
{
// lines of code
InitializeSession();
}
I'm calling the InitializeHostingEnvironment() from my Test Method like so:
public static void Test_MethodUnderTest()
{
InitializeHostingEnvironment(UN, PW);
MethodUnderTest(param1, param2, param3); -- getting exception while trying to execute this line
}
While trying to execute the line MethodUnderTest(param1, param2, param3);, I'm getting an exception - System.ArgumentNullException - Value cannot be null. Parameter name httpBrowserCapabilities. Stack trace is given below:
Since the exception says httpBrowserCapabilities is null, I tried to initialize it like HttpContext.Current.Request.Browser = new HttpBrowserCapabilities(); inside the InitializeSession() method, but now, I'm getting another exception:
What should I do now? Is the way I'm initializing HttpContext wrong? please advise.
I'm writing an unit test(using NUnit & MOQ) for a method MethodUnderTest which uses HttpContext internally to do some functionality.
Right. Don't do that. The controller should be the only method that accesses the HttpContext, and it should extract the data needed for your MethodUnderTest and use the to write to the HttpContext.
Structuring your code so that each method has a single responsibility is fundamental to writing testable code.

How to use HttpContext in Unit test? [duplicate]

I want to write a unit test which tests the function of a class called UploadedFile.
The problem I face is this class' static constructor uses HttpContext.Current property and because I am running my unit test from a class library I do not have an HttpContext at the testing time.
Look at my static constructor:
static UploadedFile()
{
if (HttpContext.Current == null)
throw new Exception("web server not available");
HttpServerUtility server = HttpContext.Current.Server;
// SET UploadedFileMappingFile Names:
_resourceFileNames = new StringDictionary();
_resourceFileNames[_suppoertedFileStructures] = server.MapPath(SupportedUploadedFileStructures);
_resourceFileNames[_supportedFileStructuresXSD] = server.MapPath(SupportedUploadedFileStructuresXSD);
_resourceFileNames[UploadedFileEnum.UploadedFileFormatENUM.CSV.ToString()] = server.MapPath(UploadedFileColumnMap);
}
What should I do in my testing environment so that HttpContext.Current won't be null and I can successfully set this:
HttpServerUtility server = HttpContext.Current.Server;
You shouldn't use HttpContext.Current directly in your function as it is close to impossible to unit test, as you've already found out. I would suggest you using HttpContextBase instead, which is passed either in the constructor of your class or as an argument to the method you are testing. This will allow the consumers of this class to pass a real HttpContextWrapper and in your unit test you can mock the methods you need.
For example here's how you could call the method:
var wrapper = new HttpContextWrapper(HttpContext.Current);
Foo.UploadedFile(wrapper);
And in your unit test (using Rhino Mocks):
var contextMock = MockRepository.GenerateMock<HttpContextBase>();
// TODO: Define expectations on the mocked object
Foo.UploadedFile(contextMock);
Or, if you prefer, use Constructor Injection.

Test if method in ClassA has been called from another method in ClassA

It is possible to test if a method has been called using Moq and dependency injection. However, is it possible to test if one method in a class calls another within the same class?
For example, I want to test that if I log a certain exception, that an information message is logged as well.
The method is:
public void Error(string message, Exception exception, long logId = 0)
{
var int32 = (int)logId;
Info("Id was converted to an int so that it would fit in the log: " + logId, int32);
Error(message, exception, int32);
}
This was my attempt at unit testing it. The test fails, is there any way that it can it be done?
void logging_an_error_with_a_long_id_also_logs_info()
{
var mock = new Mock<ILogger>();
var testedClass = new Logger();
var counter = 0;
testedClass.Error("test" + counter++, new Exception("test" + counter), Int64.MaxValue);
mock.Verify(m => m.Info(It.IsAny<string>(), It.IsAny<int>()));
}
Since the Info and Error methods are in the same class (ClassA), I don't believe I can pass ClassA as a dependency into ClassA. So does it not need tested?
The best you're going to be able to do is to make Info virtual. This will allow you to create a Mock<Logger>, set CallBase = true, and verify that Info was called.
var mock = new Mock<Logger>
{
CallBase = true
};
mock.Object.Error("test" + counter++, new Exception("test" + counter), Int64.MaxValue);
mock.Verify(m => m.Info(It.IsAny<string>(), It.IsAny<int>()));
This way, you're still calling the actual implementation of Error, but you've used Moq to verify the Info method was called.
It feels like you're trying to test the wrong thing. It's not really important that the Info method on your class is called from the Error method, what's important is that the behaviour of the Info method occurs. How it happens is an implementation detail of the class.
If I had a math class with two functions:
public int Mult(int x, int y) {
return x*y;
}
public int Sqr(int x) {
return Mult(x,y);
}
I wouldn't test that calling Sqr called out to the Mult function, I would test Sqr(4)==16. It doesn't matter if that calculation takes place in the Sqr method, or in another method of the class.
Whilst #Andrew's solution is probably what you're after, mocking the class you're testing tends to lead to tightly coupled, brittle tests.
If it's impractical to test the call by observing it's side effects, then it may be a sign that the implementation could use a bit of refactoring.

Unit Testing void returning method

I am using Moq for the first time and not really sure on the correct approach for Testing a void returning method I have. I have read this post which was helpful but didnt include many snippets of code for guidance. My method updates my DB with responses from an external webservice for a list of my car objects
My method is as below:
public void UpdateDBWithWebResponse(Response response, List<Car> cars)
{
try
{
if (response == null)
{
//Exception logged
}
foreach (var webResponse in response.Responses)
{
var car = cars.First(c => c.Id == webResponse.Id);
if (response.detailResponse == null || response.detailResponse.Values == null)
{
//Exception logged
}
foreach (var detailResponse in response.HazardResponse.Values)
{
UpdateDetailResponseOnCar(detailResponse, car);
}
}
//update the DB
_carRepository.Update(cars);
}
catch (Exception ex)
{
//log error
}
}
So it takes two parameters a Web response object and a list of car objects - UpdateDetailResponseOnCar(detailResponse, car); is a private method which maps the web reponse to the car object and then the data is saved to the DB.
I guess what I want to Test is that if the response is null then an exception is called? Similariy with the inner detail response if null is exception thrown. And then if I create a Mock response object and a mock list of cars I want to save that to a Test instance of my DB and assert that the correct values were mapped?
Does this seem like a good strategy to test the above method and has anyone got any code snippets for testing the null response throws exception and for the other cases?
First, remove the catch around everything.
Ideally you would throw exceptions where absolutely necessary, and then allow the calling code to catch them.
That way you can catch the exception in your test.
Perhaps best to use specific exceptions, e.g. ArgumentNullException for the case when response is null.
See the following for MSTest:
http://www.contentedcoder.com/2012/01/asserting-exceptions-in-mstest-with.html
What testing framework are you using? If you're using something like NUnit, you can add the ExpectedException attribute. That works if the exception is uncaught. So in your UpdateDBWithWebResponse method, you could log and rethrow it perhaps.

Expecting an exception in a test but wanting to verify dispose is called anyway

I'm unit testing a demo application, which is a POP3 client. The POP3 client implements IDisposable, so I'm trying to test a using cycle.
(I'm using nunit 2.5.2 and Moq 4.0)
/// <summary>
/// Unsuccessful construct dispose cycle, no ILogger object given.
/// Expecting ArgumentNullException. Expecting TcpClient dispose to be called.
/// </summary>
[Test]
[ExpectedException(typeof(ArgumentNullException))]
public void ConstructorDispose_LoggerNull_ArgumentNullException()
{
mockTcpClient.Setup(x => x.Dispose());
using (var popClient = new PopClient(null, mockTcpClient.Object))
{
}
mockTcpClient.VerifyAll();
}
As you can see the verifyAll method will never be invoked and the test will be successful, nonetheless. So ...
What is the best way to solve this?
Is there another way then try catch?
Update I fixed it like this for the moment:
mockTcpClient.Setup(x => x.Dispose());
var correctExceptionThrown = false;
try
{
using (var popClient = new PopClient(null, mockTcpClient.Object))
{
}
}
catch (ArgumentNullException)
{
correctExceptionThrown = true;
}
finally
{
mockTcpClient.VerifyAll();
}
Assert.That(correctExceptionThrown);
But dispose isn't called, seems to be the C# specification.
mockTcpClient.Setup(x => x.Dispose());
try
{
using (var popClient = new PopClient(null, mockTcpClient.Object))
{
}
}
finally
{
mockTcpClient.VerifyAll();
}
This doesn't answer your question (as it's already solved), but it's relevant and worth posting anyway.
[ExpectedException] is a pretty ropey way to test exceptions. It can be error prone, as the wrong line can trigger an exception of the expected type resulting in an erroneous pass. I would strongly advocate that you check out Assert.Throws() instead :)
It's nicer to use (you can query the returned exception), more readable and, above all, safer.
You can find an example here
You have already discovered that dispose really is not supposed to be called if the constructor fails. But there may still be other cases where you might want to to verify your mocks after an expected exception is thrown. I just do that in the test TearDown like this:
[SetUp]
public void SetUp()
{
this.mockFactory = new MockFactory(MockBehavior.Loose);
}
[TearDown]
public void TearDown()
{
this.mockFactory.VerifyAll();
}
[Test]
[ExpectedException(typeof(NoBananasException))]
public void EatThrowsIfNoBananasAvailable
{
var bananaProvider = this.mockFactory.Create<IBananaProvider>();
bananaProvider.SetUp(bp => bp.IsBananaAvailable).Returns(false).Verifiable();
var monkey = new Monkey(bananaProvider.Object);
monkey.Eat();
}
You seem to be testing that the injected mockTcpClient instance is disposed even if the constructor throws an exception, in which case this should work:
mockTcpClient.Setup(x => x.Dispose());
try
{
var popClient= new PopClient(null, mockTcpClient.Object);
}
finally
{
mockTcpClient.VerifyAll();
}
EDIT: Actually, try/finally would be cleaner than catching Exception. Note that you don't need to dispose popClient since no instance is created.

Categories

Resources