我有一个MVC Web应用程序,并且正在使用用于DI的Simple Injector。我的几乎所有代码都包含在单元测试中。但是,既然我已经在某些 Controller 中添加了一些遥测调用,则在设置依赖项时遇到了麻烦。

遥测调用用于将度量标准发送到Microsoft Azure托管的Application Insights服务。该应用程序不在Azure中运行,而仅在具有ISS的服务器上运行。 AI门户会告诉您有关应用程序的各种信息,包括使用遥测库发送的所有自定义事件。结果,该 Controller 需要一个Microsoft.ApplicationInsights.TelemetryClient实例,该实例没有接口(interface),并且是带有2个构造函数的密封类。我尝试过像这样注册(混合生活方式与该问题无关,为完整起见,我仅将其包括在内):

// hybrid lifestyle that gives precedence to web api request scope
var requestOrTransientLifestyle = Lifestyle.CreateHybrid(
    () => HttpContext.Current != null,
    new WebRequestLifestyle(),
    Lifestyle.Transient);

container.Register<TelemetryClient>(requestOrTransientLifestyle);

问题在于,由于TelemetryClient具有2个构造函数,所以SI会提示并且验证失败。我发现了一篇帖子,展示了如何重写容器的构造函数解析行为,但这似乎很复杂。首先,我想备份并提出以下问题:

如果我不使TelemetryClient成为注入(inject)的依赖项(只需在类中创建一个New依赖项),那么该遥测会在每次单元测试运行时发送到Azure,从而创建大量错误数据吗?还是Application Insights足够聪明以至于它知道它正在单元测试中运行并且不发送数据?

任何对此问题的“见解”将不胜感激!

谢谢

最佳答案



TelemetryClient是框架类型framework types should not be auto-wired by your container



是的,这种复杂性是有意的,因为我们想阻止人们使用多个构造函数创建组件,因为这是an anti-pattern

就像使用@qujck所指出的那样,您无需进行 Autowiring ,只需进行以下注册:

container.Register<TelemetryClient>(() =>
    new TelemetryClient(/*whatever values you need*/),
    requestOrTransientLifestyle);



非常不可能。如果要测试依赖于此TelemetryClient的类,则最好改用伪造的实现,以防止单元测试变得脆弱,缓慢或污染Insight数据。但是即使测试不是问题,根据Dependency Inversion Principle,您也应该依赖(1)由您自己的应用程序定义的(2)抽象。使用TelemetryClient时,两点都会失败。

您应该做的是在上为定义一个(或什至多个)抽象,特别是针对您的应用程序量身定制的。因此,请勿尝试使用可能的100种方法模仿TelemetryClient的API,而应仅在 Controller 实际使用的接口(interface)上定义方法,并使其尽可能简单,以便使 Controller 的代码更简单-和-您的单元测试更加简单。

定义良好的抽象之后,可以创建一个在内部使用TelemetryClient的适配器实现。我为您注册此适配器的图像如下:
container.RegisterSingleton<ITelemetryLogger>(
    new TelemetryClientAdapter(new TelemetryClient(...)));

在这里,我假设TelemetryClient是线程安全的,可以作为单例工作。否则,您可以执行以下操作:
container.RegisterSingleton<ITelemetryLogger>(
    new TelemetryClientAdapter(() => new TelemetryClient(...)));

在这里,适配器仍然是单例,但是提供了一个允许创建TelemetryClient的委托(delegate)。另一个选择是让适配器在内部创建(或处置)TelemetryClient。这也许会使注册更加简单:
container.RegisterSingleton<ITelemetryLogger>(new TelemetryClientAdapter());

关于c# - 将Application Insights与单元测试一起使用?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33815397/

10-12 06:20