Reputation: 2083
This is a simplified model of my class.
public static FooFactory
{
public void CreateFooByUrl(string url)
{
try
{
// business logic
}
catch(Exception exc)
{
ApplicationLogger.LogError(exc);
}
}
}
ApplicationLogger
is a static class which is used across the solution. How can I verify that error was logged?
This is example of my test method.
[TestMethod]
public void CreateFooExpectedError()
{
// Arrange
string testUrl = "fakeUrl";
// Act
FooFactory.CreateFoo(testUrl);
// Assert
/ApplicationLogger.LogError();
}
How to check that LogError
method was called? Does it a test case?
Upvotes: 0
Views: 132
Reputation: 32704
You have a hard dependency on ApplicationLogger
. That's not good. Now you can't test that CreateFooByUrl
works without actually logging something. Instead, have it use an IApplicationLogger
(an interface) and then you can provide a mock implementation of that interface as part of unit testing. This will probably mean you either need to make FooFactory
non static (you can't have a non static method in a static class anyways like you've shown) or change CreateFooByUrl
to accept an IApplicationLogger
as a parameter (messier).
Here's the clean way:
public interface IApplicationLogger
{
void LogError(Exception exception);
}
public class ApplicationLogger : IApplicationLogger
{
public void LogError(Exception exception)
{
//do stuff
}
}
public class FooFactory
{
private readonly IApplicationLogger _logger;
public FooFactory(IApplicationLogger logger)
{
_logger = logger;
}
public void CreateFooByUrl(string url)
{
try
{
// business logic
}
catch(Exception exception)
{
_logger.LogError(exception);
}
}
}
//now for the unit test
public void TestCreate()
{
//arrange
var mockLogger = new Mock<IApplicationLogger>(MockBehavior.Strict);
mockLogger.Setup(m => m.LogError(It.IsAny<Exception>()));
var factory = new FooFactory(mockLogger.Object);
//act
factory.CreateFooByUrl("something that will cause exception");
//assert
mockLogger.Verify(m => m.LogError(It.IsAny<Exception>()));
}
This is much better from a Separation of Concerns perspective. Why should FooFactory care how things get logged? It just needs to be able to log things. That's why it's better to code against an interface. Then if you ever want to switch logging implementations you just have to create a new class that implements IApplicationLogger and everything will magically work.
Upvotes: 4