I have an interface which is used in an MVC controller which gets some data. To keep it simple the interface so far looks something like this:
public interface IDataProvider
{
DataModel GetData();
}
I have appropriate unit tests for this interface where it is called in the action. However, in the real implementation this will call a web service which of course could throw an exception, therefore if it does I want to write a test to ensure that I log a message if an error occurs.
To do this I have a logger interface which is actually an interface to NLog called ILogger. I could do this:
public interface IDataProvider
{
DataModel GetData(ILogger logger);
}
This would allow me to run unit tests for the logger making it nice and simple. However, I don't think this is the right way of doing this because the logger is really unrelated to this method. Also, if I start adding other methods to this interface which I need logging for then I will have to include the logger in the parameter of all of those methods as well.
The best way I can think of right now is to include the logger in the constructor of my implementation which might look like this:
public class DataProvider : IDataProvider
{
private readonly ILogger _logger;
public DataProvider(ILogger logger)
{
_logger = logger;
}
public DataModel GetData()
{
// CODE GOES HERE
}
}
However this means that I cannot test the logger in my unit tests. What is the best way to achieve this so that I can keep the logger separate from the method and make it testable?
I'll appreciate any help, thanks.
EDIT:
I realise I missed out unit testing code here is what I mean:
At the moment I am ensuring that GetData is called in my action this way:
var controller = new DataController(_dataProvider.Object);
controller.Index();
_dataProvider.Verify(dataProvider => dataProvider.GetData());
What I'd like to do is the same but for the logger but only if an exception is thrown like this:
_dataProvider.Setup(dataProvider => dataProvider.GetData()).Throws<WebException>();
var controller = new DataController(_dataProvider.Object);
controller.Index();
_logger.Verify(logger => logger.ErrorException(It.IsAny<string>(), It.IsAny<Exception>());
Obviously logger would be given to data provider in the setup. I hope that makes a bit more sense.