【发布时间】:2018-10-18 14:10:36
【问题描述】:
我已经实现了自己的记录器,它遵循 ILogger 接口。在内部,它有 AppInsights 客户端,这就是我的记录器实际记录的内容。这是我的课程的简化版本:
public class AppInsightsLogger : ILogger
{
internal TelemetryClient Client { get; set; }
public AppInsightsLogger(string instrumentationKey)
{
TelemetryConfiguration.Active.InstrumentationKey = instrumentationKey;
Client = new TelemetryClient();
}
public void Log<T>(LogLevel logLevel, EventId eventId, T state, Exception exception,
Func<T, Exception, string> formatter)
{
if (string.IsNullOrEmpty(eventId.Name))
{
StackFrame frame = new StackFrame(1);
var method = frame.GetMethod();
var type = method.DeclaringType;
var name = method.Name;
eventId = new EventId(eventId.Id == 0 ? BitConverter.ToInt32(Guid.NewGuid().ToByteArray(), 0) : eventId.Id, $"{type}:{name}");
}
var props = new Dictionary<string, string>
{
{ "EventId", eventId.Id.ToString() },
{ "EventName", eventId.Name }
};
var telemetry = new EventTelemetry(eventId.Name);
if (!string.IsNullOrEmpty(state.ToString()))
{
telemetry.Properties.Add("SummaryMessage", state.ToString());
}
foreach (var property in props)
{
telemetry.Properties.Add(property);
}
Client.TrackEvent(telemetry);
}
}
我想验证的是(可能是错误的,也请告知),当我调用我的AppInsightsLogger 类Log 方法时,它实际上尝试调用TelemetryClient 的TrackEvent 方法。我正在考虑这样的测试:
[Fact, IsUnit]
public void Test_Telemetry_Log()
{
var mock = new Mock<ILogger>();
mock.Setup(m =>
m.Log<string>(It.IsAny<LogLevel>(), It.IsAny<EventId>(), It.IsAny<string>(), null, null));
mock.Object.Log(LogLevel.Information, new EventId(1, "test"), "test", null, null);
mock.Verify();
}
但是当我运行这个测试时(它通过了),它并没有被我的代码覆盖率监视器(Jetbrain 的 dotCoverage)覆盖。
知道如何正确执行此测试以便正确覆盖代码吗?我也在使用 起订量。
问题是因为它是一个模拟实例吗?我不能模拟 TelemetryClient,因为我的另一个想法是测试这是 AppInsightsLogger 的一个实例,然后验证 TelemetryClient.log 被称为但它是一个密封的类,使这个测试变得复杂:-/
提前感谢任何提示! 注意:我对编写测试还很陌生 - 我了解这些概念,但没有实际执行。
【问题讨论】:
-
代码覆盖率监控器是对的:你在模拟你正在测试的类,而实际的实现永远不会运行。与其模拟
ILogger,不如在AppInsightsLogger的真实实例上调用Log 方法,然后模拟TelemetryClient。 -
TelemetryClient 虽然是一个密封类 :( 但这是有道理的,因为它是模拟实例 - 不知道如何测试这个
-
将遥测客户端封装/包装在您控制的抽象后面,并将其注入记录器。记录器与实现问题的耦合过于紧密,因此难以单独进行单元测试。
标签: c# unit-testing testing moq code-coverage