1

I am implementing a custom ILogger (interface for logging) I have succesfully developed implementations of it with some famous loggers like Serilog or Log4Net. Now i want to create a memory logger, that stores all the logs inside a List (memory).

Since the List will only exist in the MemoryLogger:ILogger , I think that make it part of the contract of ILogger will be a bad workaround. I need some ideas about how to make that List accesible from the ILogger because it will be used in some Asserts in unit testing, for example. Do you have any ideas? Any workAround?

Thanks guys!!

  • "[...] because it will be used in some Asserts in unit testing" You should explain a bit more how you want to unit test it. If it's not possible to test it through the public interface, it's not going to be accessible from the clients. Unit testing makes assertions from the point of view of the client. It shouldn't know about the implementation. – Vincent Savard Apr 20 '18 at 12:21
  • For example i want to know it , when a fatal error ocurred, it gets logged – Badulake Apr 20 '18 at 12:23
  • What do you envision your MemoryLogger to be? Sure, you say that you want to save logs in memory, but what purpose will that serve? How do you intend to access the content of the logs outside of tests? – Vincent Savard Apr 20 '18 at 12:40
  • Unit testing is used to test an implementation rather than an interface. – HungDL Apr 20 '18 at 13:09
  • @HungDL This is a common misconception. Unit testing is about asserting the behaviour of an implementation through its public interface (interface here meaning the public API, not an interface in the Java/C# sense). You do not care how it is implemented as long as the outcome matches the expectations. In this case, if the public interface of the MemoryLogger does not allow to query its state, then there's no outcome or behaviour to test because its state will always be hidden to the clients. – Vincent Savard Apr 20 '18 at 13:59
7

You don't need an interface for your MemoryLogger. You just need to pass that instance into the class being tested. A simplified test case would be something like this:

public void ShouldLogTraceMessagesForStartStop()
{
    var logger = new MemoryLogger();

    var thingToTest = new LoggingThing(logger);
    thingToTest.DoSomething();

    var traceMessages = logger.Messages.Where(m=>m.Level == Level.Trace).ToList();

    Assert.That(traceMessages.Length).Is(2);
    Assert.That(traceMessages[0]).Contains("start");
    Assert.That(traceMessages[1]).Contains("stop");
}

The only thing you need to make this work is that your constructor takes your ILogger: LoggingThing(ILogger logger). From LoggingThing's perspective, it has an ILogger and it is perfectly content to use it as it is supposed to. From the unit test's perspective, you have a MemoryLogger and you can query it how you want to.

If you have a dependency injection setup like ninject, then it should have a mechanism to register a singleton.

  • Nice point of view – Badulake Apr 20 '18 at 21:52
4

I need some ideas about how to make that List accesible from the ILogger because it will be used in some Asserts in unit testing, for example.

You don't. Modifying the interface based on a single implementation's requirements is a bad idea. Modifying the visibility of a class for unit testing alone is also a bad idea. Just don't do it.

(And really, if you're writing unit tests against the one implementation, the tests *already* know it's that specific implementation - why involve the interface at all?)

  • You are completely right – Badulake Apr 20 '18 at 21:35
-1

If I understand right, you are looking for a way to READ the logged data.
That is something you didn't need before, when logging to file.
You should create a new interface ILoggerRead that exposes the list from ILoger object.
With it you will be able to expose the logged memory data List GetLoggeddata()
Then you can implement it in your memory logger and do whatever with it.

  • Dunno, while the Idea is fine, it is in fact overkill for OP test case, as said Telastyn, in a unit test it's perfectly fine to fix the logger as being the Memorylogger instead of using the interface. – Walfrat Apr 26 '18 at 9:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.