MediatR处理程序中的ASP.NET基础设施

11
我更喜欢让我的处理程序摆脱 ASP.NET 基础设施,因为它很难测试(即使在 ASP.NET Core 中也是如此)。但有时您会有像 UserManager(我想有一天知道它为什么不是一个接口)、HttpContext 等依赖项,单元测试会变成一个模拟地狱。
我尝试使用集成测试来解决这个问题,通过创建 TestServer 并为每个 API 调用初始化所有 ASP.NET 基础架构。这样做效果还不错,但有时看起来有些过度,特别是当我想测试处理程序的简单逻辑时。虽然它解决了模拟 ASP.NET 基础结构的技术问题,但它仍然保留了将 ASP.NET 基础设施引入处理程序的架构问题(如果您认为它是这样的)。
我想知道有哪些推荐的方法来处理这个问题?

如果您有兴趣抽象化UserManager和Identity,请查看我在这里给出的答案:https://dev59.com/0Jnga4cB1Zd3GeqPTRIQ#38464229 - Nkosi
我发现Jimmy Bogard和Patrick Lioi分别写的这篇这篇文章非常有帮助,可以让处理程序保持简洁且易于测试。 - trevorc
@trevorc,这些都是很好的方法。您能否写一篇关于您的经验的答案? - SiberianGuy
3个回答

7

我了解你的痛苦。我偶然发现了Jimmy Bogard撰写的一篇绝妙的博客文章,他通过使用Martin Fowler所谓的Subcutaneous Tests来处理这个问题。具体的解释请参考专家,但简而言之,皮下测试可以避免所有难以测试的UI方面。

厚颜无耻地宣传一下:我正在编写一个维基页面,展示在GitHub上一个样例端到端项目中使用这些模式。它不难理解,但可能太多代码了,不能在SO回答中发布。

总之:

  • 如果使用MediatR正确,你的控制器应该非常轻巧,从而使得测试它们变得毫无意义
  • 你想要测试的是你的处理程序。
  • 但是,你希望将你的处理程序作为真实的流程的一部分进行测试。

解决方法:

  1. 将http请求封装在事务中。
  2. 构建一个测试夹具,模仿应用程序的Startup.cs文件。
  3. 设置一个测试数据库服务器,以执行查询和命令,但每次测试后都会重置。

基本上就是这样。每次针对处理程序之一运行集成测试时:

  • 虚拟托管环境,但在真实世界的测试中启动了您的应用程序。
  • 将查询或命令封装在模仿DbContext的事务中。
  • 对真实数据库执行处理程序,然后重置。

我会在我的答案中添加更多代码示例,但在我提供的博客文章和wiki之间,跟随那里的代码示例要容易得多。

编辑8/2021:

坚持使用源代码。Jimmy Bogard在他的GitHub页面上保持了contoso大学项目的最新状态。另一个很棒且稍微高级一些的例子是Kamil Grzybek的模块化单体项目。它也经常在他的GitHub页面上更新。


2
无论是否使用Mediatr,您都应该尽量让控制器只处理基本的传递逻辑,并从中调用注入的业务逻辑类来执行实际工作。通过将它们与业务逻辑的接口一起注入,您的控制器依赖项可以很容易地在单元测试中进行模拟,并且您的测试可以专注于它们是否正确实现这些接口并仅执行基本的输入/输出路由工作。而且您的实际业务逻辑也可以更轻松地进行测试。
对于那些静态的类,例如读取web.config设置的类,我非常喜欢的一种策略是在它们周围创建一个带有接口的包装类。虽然ConfigurationManager是静态的,但我仍然可以编写一个常规类,并为其放置方法或属性以从配置管理器中读取特定设置(最好是语义化命名)。现在,我可以通过模拟接口并设置不同的返回值来轻松地模拟任何配置的设置(或缺少设置)来进行测试。

1
我认为这取决于您最终想要获得的信心水平。如果您想确保整个系统按预期工作,则使用TestServer进行集成测试可能是正确的方法。
MediatR的一个优点是它允许您将业务逻辑与使用它的应用程序解耦,这就是为什么在最高级别(比如控制器)没有逻辑而只有对中介器的委托。
话虽如此,您说得对,有时您的逻辑需要来自托管应用程序的信息。例如,发出请求的用户可以在HTTP上下文中访问。
在这种情况下,如果您想避免设置测试HTTP服务器来测试逻辑是否正常工作,可以在抽象中表示该信息,然后您的处理程序将依赖于该抽象。您的测试可以在使用真实系统的同时模拟该依赖项以进行其他所有操作。
这样讲清楚了吗?

是的,谢谢!我也考虑过使用 Mediatr 预处理来“丰富”命令/查询与框架特定的内容(例如,如果我需要获取某种 URL,我不必注入 IUrlHelper),但这种方法似乎很繁琐。 - SiberianGuy
我不确定我理解了。你能再详细解释一下吗? - Mickaël Derriey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接