【发布时间】:2020-08-27 03:46:11
【问题描述】:
我正在使用 SpecFlow 为 API 集成测试工具提供支持,该工具将提供新 UI API 的实时文档和测试覆盖率。我编写了一些功能文件,最终达到了我尝试并行运行大约 60 个测试的地步。但是,虽然我可以毫无问题地单独运行这些功能,但在尝试使用 Visual Studio 2019 测试运行程序和 XUnit 运行程序插件并行运行它们时遇到间歇性故障。
任何给定的 SpecFlow 场景都将使用来自两个不同步骤绑定类的步骤,并且每个步骤绑定类都可能需要注入最多三个上下文对象,这些对象旨在捕获场景期间的状态并在场景结束后清理环境完成。例如,一个功能可能如下所示:
Scenario: Retrieving Message records returns data
Given I have created the following ClientAccounts:
| Index | SiteID | IsActive |
| 1 | 1 | 1 |
And I have created the following Logins:
| Index | IsActive |
| 1 | 1 |
And I have created the following Messages:
| MessageID | MessageText |
| 1 | Asdfasdf |
When I send an authentication request using the first Login and the IP Address 127.0.0.1
And I send a read request to the v1 Message endpoint for the first Message record created:
Then the first Message response should be equivalent to the following data for the first Message record created:
| MessageTest |
| Asdfasdf |
前三个步骤属于一个名为 DatabaseSteps 的类,它的构造函数接受一个 DataUtility 类的实例,该实例促进对数据库的 CRUD 操作,并跟踪作为测试执行的一部分创建的记录。还有一些 [StepArgumentTransformation] 绑定将这些表转换为可以插入到数据库中的数据库对象。
第四、第五和第六步属于额外的步骤类,它们的构造函数将用于数据库访问的 DataUtility 和存储会话信息以及有关先前保存的 API 响应的信息的 ApiClientContext 作为依赖项,按顺序断言在“然后”阶段获得的实际响应。 DataUtility 类实现 IDisposable 以简化测试后清理。
基于documentation,我预计通过内置 DI 容器注入的上下文类将是线程安全的。但是,我发现无论是使用 DataUtility 实现 IDisposable 还是不声明接口并直接从 [AfterScenario] 挂钩调用 Dispose(),在大多数测试运行期间,与预期返回数据有关的测试都会失败。很难确定,因为解决并发问题很糟糕,但似乎 DataUtility 实例正在场景之间共享,并且当任何给定场景在数据实用程序上调用 Dispose() 时,我搭建的所有测试数据都是清除 - 即使在其他不相关的情况下也是如此。当我既没有在 DataUtility 类上声明 IDisposable 也没有从钩子调用 Dispose() 时,测试会毫无意外地执行。是否有一种特殊的方式需要我设置一个注入的上下文类,以便每个场景都有自己的该类的实例?
其他详细信息:VS2019、SpecFlow 3、XUnit 测试运行器
【问题讨论】:
-
DataUtility 是你创建的类吗?
-
是的 - DataUtility 是我为促进数据库交互而编写的一个类。它将一个 IConfiguration 实例(在 BeforeScenario 挂钩中注册到 ConfigurationBuilder)作为构造函数参数,并用于获取数据库连接字符串。它包含两个类
ProductDatabase和STSDatabase的成员实例,它们本身包含数据库提供程序类(在各自的数据库中执行 CRUD 操作)和各种 List其中 T 是已创建的数据库对象 POCO然后可以在场景结束时删除它们。 -
上下文注入应该是线程安全的。如果没有看到 DataUtility 类中的步骤定义和代码,以及错误消息和堆栈跟踪,我认为我们无法为您提供帮助。
-
我认为精简版就足够了。
-
我昨天和今天花了很多时间在我的 DAL 中添加日志以了解在数据库中创建和删除对象的操作,最终在我与 Dapper 一起使用的辅助库;它选择了一个名称以 GUID 结尾的字段,并在自动构建的删除查询中使用它,而不是使用实际的 ID 字段。由于我用于数据库的对象库是与产品团队共享的,所以我不能用我自己的属性来装饰它,并且愚蠢地陷入了这个问题。谢谢@GregBurghardt 的帮助!
标签: c# bdd specflow context-injection