MediatR处理程序中的ASP.NET基础结构

时间:2017-01-30 08:58:04

标签: asp.net asp.net-web-api asp.net-core mediatr

我更喜欢让我的处理程序免于很难测试的ASP.NET基础结构(是的,甚至在ASP.NET Core中)。但有时它会发生,你有一个依赖,比如UserManager(我想知道有一天为什么它不是一个接口),HttpContext等等。单元测试变成了一个嘲弄地狱。

我尝试使用集成测试来处理它,方法是创建一个TestServer并为每个api调用初始化所有ASP.NET基础结构。它工作得很好,但如果我想测试我的处理程序的简单逻辑,有时看起来有点矫枉过正。虽然它解决了模拟ASP.NET基础结构的技术问题,但它仍然存在将ASP.NET基础结构放入处理程序的架构问题(如果您考虑的话)。

我想知道处理它的推荐方法是什么?

3 个答案:

答案 0 :(得分:5)

我感觉到你的痛苦。我偶然发现了吉米·博加德(Jimmy Bogard)的一个奇妙的blob post,它使用了马丁福勒所称的Subcutaneous Tests来处理这个问题。我将向那些专家留下深刻的解释,但简而言之,皮下测试只是避免了UI的所有难以测试的方面。

无耻插件:我目前正在编写一个wiki,在github上的示例端到端项目中演示这些模式。这并不难理解,但可能有太多的代码要发布SO答案。

总结:

  • 如果您正确使用MediatR,您的控制器应该非常薄,这使得测试它们毫无意义
  • 您要测试的是您的处理程序。
  • 但是,您希望将处理程序作为现实世界管道的一部分进行测试。

要解决:

  1. 在事务中包装http请求。
  2. 构建一个模拟应用程序Startup.cs
  3. 的测试夹具
  4. 设置测试数据库服务器以执行查询和命令,但也会在每次测试后重置。
  5. 基本上就是这样。每次针对其中一个处理程序运行集成测试时:

    • 托管环境已被模拟,但您的应用程序是在现实世界的测试中启动的。
    • 您的查询或命令包含在模仿您的DbContext的事务中。
    • 处理程序针对真实数据库执行,然后重置。

    我会在答案中添加更多代码示例,但在博文和我提供的wiki之间,可以更容易地遵循那里的代码示例。

答案 1 :(得分:1)

我会说这取决于你最终想要获得的信心程度。如果你想确保整个系统按预期工作,那么使用TestServer进行集成测试可能就好了。

然而,MediatR的一个优点是,它允许您将业务逻辑与使用它的应用程序分离,这就是为什么在最高级别,让我们说在控制器中,没有逻辑,只是委托给调解员。

话虽这么说,你是对的,有时你的逻辑需要来自托管应用程序的信息。一个例子是发出请求的用户,可以在HTTP上下文中访问。

在这种情况下,如果您想避免设置测试HTTP服务器来测试逻辑工作,您可以在抽象中表示该信息,然后您的处理程序将依赖于该抽象。然后,您的测试可以模拟该依赖关系,同时将真实系统用于其他所有事情。

这有意义吗?

答案 2 :(得分:1)

Mediatr或者不,你应该总是尝试只在控制器中的逻辑上进行非常基本的传递,并从那里调用注入的业务逻辑类来完成实际的工作。当您向它们注入与此业务逻辑的接口时,您的控制器就会出现这种情况。在单元测试中很容易模拟依赖关系,如果他们正确地实现了这些接口并且只做路由输入/输出的基本工作,那么测试可以集中精力。您的实际业务逻辑可以更轻松地进行测试。

对于那些静态的类,例如读取web.config设置,我喜欢的一个策略是围绕它们创建一个接口包装类。虽然ConfigurationManager是静态的,但我仍然可以编写一个带有接口的常规类,我将方法或属性设置为从Configuration Manager读取特定设置(最好是语义命名)。现在,我可以通过模拟界面和设置不同的返回值,轻松地在我的测试中模拟任何已配置的设置(或缺少它)。