c# - Unit Testing using Moq and Autofac -


i have following logger logger class , want know best unit testing it.

some observations:

  1. i needed create interface ifilewrapper in order break dependency system.io dependency , been able user dependency injection (autofac)
  2. i able unit testing method filewrapper.writelog implementing ifilewrapper using memorystring if wanted test expected behavior inside method won't able (e.g: throwing exceptions, incorrect path , filename, etc.)

    /// <summary> /// creates instance of type <see cref="filelogger"/> /// </summary> /// <remarks>implements singleton pattern</remarks> private filelogger() {     filename = string.format("\\{0: mmm dd, yy}.log", datetime.now);     path = environment.currentdirectory;      filewrapper = containerbuilderfactory.container.resolve<ifilewrapper>(); }  /// <summary> /// log <paramref name="message"/> in <paramref name="path"/> specified. /// <paramref name="username"/>, <paramref name="host"/> must supplied /// </summary> /// <example> ///     <code> ///         var handler = new loggerhandlerfactory(); ///         var logger = handler.gethandler<filelogger>(); ///         logger.log("hello csharplogger"); ///     </code> /// </example> /// <exception cref="argumentnullexception"></exception> /// <exception cref="argumentexception"></exception> /// <exception cref="notsupportedexception"></exception> /// <exception cref="filenotfoundexception"></exception> /// <exception cref="ioexception"></exception> /// <exception cref="securityexception"></exception> /// <exception cref="directorynotfoundexception"></exception> /// <exception cref="unauthorizedaccessexception"></exception> /// <exception cref="pathtoolongexception"></exception> /// <exception cref="argumentoutofrangeexception"></exception> /// <exception cref="formatexception"></exception> public void log(string message, loglevel level = loglevel.info) {     lock (_current)     {         var configlevel = csharploggerconfiguration.configuration.getloglevel();          if (configlevel != loglevel.off & level != loglevel.off && configlevel >= level)         {             try             {                 filewrapper.writelog(string.concat(path, filename), message, level);             }             catch (csharploggerexception)             {                 throw;             }         }     } } 

so, created following unittesting using moq:

 //arrange         csharploggerconfiguration.configuration.setloglevel(loglevel.debug);          var mock = new mock<ifilewrapper>();         mock.setup(x => x.writelog(it.isany<string>(), it.isany<string>(), it.isany<loglevel>()));          logger.filewrapper = mock.object;          //act         logger.log("hello csharplogger", loglevel.debug);         logger.log("hello csharplogger", loglevel.warn);          //assert          mock.verify(x => x.writelog(it.isany<string>(), it.isany<string>(), it.isany<loglevel>()), times.exactly(2)); 

so far good. i'm not confortable line: logger.filewrapper = mock.object; keep filewrapper propety private.

any advise welcome.

i'll publishing code http://csharplogger.codeplex.com/ in case want more details.

use constructor injection. in short; instead of providing service (in case file wrapper) setting property, make logger have public constructor takes ifilewrapper argument.

public class logger {     public logger(ifilewrapper filewrapper)     {         filewrapper = filewrapper;     }      public ifilewrapper filewrapper { get; } }  // in test: var logger = new logger(mock.object); 

to answer question having singleton file wrapper more thoroughly, here's code sample application (non-test) code:

public static class filewrapperfactory {     private static ifilewrapper _filewrapper;      public static ifilewrapper getinstance()     {         return _filewrapper ?? (_filewrapper = createinstance());     }      private static ifilewrapper createinstance()     {         // necessary setup here         return new filewrapper();     } }   public class stuffdoer {     public void dostuff()     {         var logger = new filelogger(filewrapperfactory.getinstance());          logger.writelog("starting stuff...");          // stuff          logger.writelog("stuff done.");     } } 

since filewrapperfactory maintains static instance of file wrapper, you'll never have more one. however, can create multiple loggers that, , don't have care. if you, in future, decide it's ok have many file wrappers, logger code doesn't have change.

in real-world application, i'd advice choose kind of di framework handle book-keeping you; have excellent support singleton instances, doing filewrapperfactory above (but in more sophisticated , robust way. filewrapperfactory isnt' thread-safe, example...).


Comments

Popular posts from this blog

mysql - Dreamhost PyCharm Django Python 3 Launching a Site -

java - Sending SMS with SMSLib and Web Services -

java - How to resolve The method toString() in the type Object is not applicable for the arguments (InputStream) -