Ich habe die folgende Logger-Logger-Klasse und ich möchte wissen, die beste zu Unit-Test es.Unit Testing mit Moq und Autofac
Einige Beobachtungen:
- Ich brauchte die Schnittstelle IFileWrapper zu brechen, um die Abhängigkeit mit System.IO Abhängigkeit und in der Lage zu Benutzer Dependency Injection (Autofac)
ich Unit-Tests war in der Lage zu schaffen die Methode FileWrapper.WriteLog durch Implementieren von IFileWrapper mit einem MemoryString, aber wenn ich ein erwartetes Verhalten innerhalb der Methode testen wollte, kann ich nicht (z. B .: Ausnahmen, falscher Pfad und Dateiname usw.)
/// <summary> /// Creates an instance of type <see cref="FileLogger"/> /// </summary> /// <remarks>Implements the 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 the <paramref name="Message"/> in the <paramref name="Path"/> specified. /// The <paramref name="UserName"/>, <paramref name="Host"/> must be 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 habe ich die folgende Unittesting mit 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 weit so gut. Was ich nicht confortable bin, ist mit dieser Zeile: logger.FileWrapper = mock.Object; Ich möchte FileWrapper property privat halten.
Jede Beratung ist willkommen.
Ich werde den Code http://csharplogger.codeplex.com/ veröffentlichen, falls Sie weitere Informationen wünschen.
Hallo Tomas , Danke für deine Antwort. Ich habe darüber nachgedacht, aber da meine Klasse eine Singleton-Klasse ist, sollte es nicht funktionieren, oder? – user1922446
Sie müssen vermeiden, Ihren Service als eine 'statische Klasse' zu haben, da Sie eine Instanz davon injizieren müssen, um dieses Muster anzuwenden.Die Verwendung einer statischen (Singleton) -Instanz * ist kein Problem - die Tatsache, dass die Instanz Singleton ist, liegt jedoch nicht in der Verantwortung des Loggers *. (Es liegt in der Verantwortung desjenigen, der den Logger instanziiert, die Instanz des Dateiwrappers bereitzustellen und somit jedes Mal die Singleton-Instanz auszuwählen.) –
@ user1922446: Siehe mein Update für eine detailliertere Erklärung dessen, was ich meine. –