我有一个MVC网络应用程序,我正在使用Simple Injector进行DI . 我的几乎所有代码都包含在单元测试中 . 但是,现在我已经在某些控制器中添加了一些遥测调用,我在设置依赖项时遇到了麻烦 .
遥测调用用于将指标发送到Microsoft Azure托管的Application Insights服务 . 该应用程序未在Azure中运行,只是一个带有ISS的服务器 . AI门户网站会告诉您有关应用程序的各种信息,包括使用遥测库发送的任何自定义事件 . 因此,控制器需要一个Microsoft.ApplicationInsights.TelemetryClient实例,该实例没有接口,并且是一个带有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成为一个注入的依赖项(只是在类中创建一个新的),那么在每次运行单元测试时是否会将遥测发送到Azure,从而产生大量错误数据?或者Application Insights是否足够聪明,知道它在单元测试中运行,而不是发送数据?
对此问题的任何“见解”将不胜感激!
谢谢
5 回答
这个
TelemetryClient
是一个框架类型和framework types should not be auto-wired by your container .是的,这种复杂性是有意的,因为我们想阻止人们创建具有多个构造函数的组件,因为这是an anti-pattern .
正如@qujck已经指出的那样,您可以简单地进行以下注册,而不是使用自动布线:
非常不可能 . 如果要测试依赖于此
TelemetryClient
的类,则最好使用虚假实现,以防止单元测试变得脆弱,缓慢或污染Insight数据 . 但即使测试不是问题,根据Dependency Inversion Principle,您应该依赖于(1)由您自己的应用程序定义的(2)抽象 . 使用TelemetryClient
时,两个点均失败 .你应该做的是在
TelemetryClient
上定义一个(或者甚至是多个)抽象,它们是 especially tailored for your application . 所以不要试图用它可能的100种方法来模仿_1342443的API,而只是在控制器实际使用的接口上定义方法,并使它们尽可能简单,这样你就可以使控制器的代码更简单 - 和 - 你的单元测试更简单 .在定义了良好的抽象之后,您可以创建一个在内部使用
TelemetryClient
的适配器实现 . 我想象你注册这个适配器如下:这里我假设
TelemetryClient
是线程安全的,可以作为单例工作 . 否则,您可以执行以下操作:这里的适配器仍然是一个单例,但是提供了一个允许创建
TelemetryClient
的委托 . 另一个选择是让适配器在内部创建(并可能配置)TelemetryClient
. 这可能会使注册更简单:Application Insights有example单元通过模拟
TelemetryChannel
来测试TelemetryClient
.TelemetryChannel
实现ITelemetryChannel
所以很容易模拟和注入 . 在此示例中,您可以记录消息,然后稍后从Items
收集它们以获取断言 .使用Josh Rostad的article编写我的模拟TelemetryChannel并将其注入我的测试中,我取得了很大的成功 . 这是模拟对象:
然后在我的测试中,一个本地方法来启动模拟:
最后,运行测试!
如果你不想沿着抽象/包装路径走下去 . 在您的测试中,您可以简单地将AppInsights endpoints 定向到模拟轻量级http服务器(在ASP.NET Core中很简单) .
appInsightsSettings.json
如何在ASP.NET Core中设置"TestServer" http://josephwoodward.co.uk/2016/07/integration-testing-asp-net-core-middleware
另一种选择没有进行抽象路线是在运行测试之前禁用遥测:
TelemetryConfiguration.Active.DisableTelemetry = true;