WebAPI 和事务的集成测试

Integration Tests for WebAPI and transactions

我有一个面向 客户端的 ASP.NET Web API,它既有直接 SQL 服务器调用,也有调用 other ASP.NET Web APIs做数据操作。我想对 客户端 REST API 进行端到端集成测试,以测试另一个名为 REST API 的路由以及各种数据操作都成功了。

我想做的测试是 (1) 不同 REST API 的路由是正确的,以及 (2) 通过 REST API 添加和更新客户是成功的。简单测试添加一个客户,可以确保路由正确,数据操作成功。

我想在完成测试后回滚事务。例如,在测试期间,通过 REST API 创建了一个新客户,如 http://localhost/Customer/POST,并在测试结束时删除了该用户。

REST 是否可以进行事务操作API,欢迎提出任何关于集成测试的建议。我在 Visual Studio 2013 环境中使用 NUNIT。

不幸的是,当前的选项并不理想,这是我在一个相对较大的项目上设置的 - 这与 here 上的官方测试指南相距不远。这一切都依赖于 build/test/deploy 流程的自动化(即 ALM- 应用程序生命周期管理,我们使用 Visual Studio Release Manager 2013)

1).在 CI 服务器上,我们 运行 对每次签入执行一系列单元测试,通过直接实例化控制器 class 并调用 get/put/post/delete 方法来执行一些基本测试,就像我们使用的那样任何其他单元测试。这些使用模拟后端(无数据库连接)层,因此我可以测试 API、数据、业务层,它们都相互独立。

2).在每晚自动部署到 "integration" 环境时,我们 运行 以上分别再次检查项目的每一层,然后将所有资产部署到集成服务器。一旦部署,我们然后 运行 一些使用 "ASP.net Web API Client Library" 的构建构造检查(在 nuget 和 asp.net 网站上寻找它们)从 [=24= 执行真正的端到端测试] 一直通过每一层到数据库,在单元测试结束时,在一些断言之后我们 运行 一个简单的删除查询来回滚数据。不幸的是,目前webapi中没有"Transactions"的概念,你必须自己创建。为了将单元测试与构建确认/验收测试分开,我们在单元测试上有一个自定义操作过滤器,允许我们排除给定的测试。所以我们的构象测试看起来像这样:

[Test, ConformationTest]
Public void TestGetCustomer(){
   //build get request here
}

3).然后构建在部署到 LIVE 之前通过正式测试阶段(跨分支手动合并),因为我们使用发布管道("Visual Studio Release manager 2013")我们知道环境之间的构建是相同的,因此我们只做了少数在实时部署上获取请求以确保 API 在负载平衡器上重新启用服务器之前 运行ning。

我们这样做的原因是 Web API 需要托管在某个地方以对其进行端到端测试,单元测试会在签入时立即捕获大多数错误 - 以及与旋转相关的夜间任何路由如果你有几个开发人员整天定期检查,那么每次检查都安装一个 VM 是昂贵的。这确实涵盖了大部分方面,但正如我所说,并不是 100% 理想。

这是您可以做到的一种方式。

通过将当前事务添加到测试服务器。当请求发送到 TestServer 时。您可以将事务设置为当前事务以启用 UnitTest 和 TestServer 之间的事务流。

using (var server = TestServer.Create(app =>
        {

            app.Properties.Add(new KeyValuePair<string, object>("Transaction", Transaction.Current));

            app.Use((context, next) =>
            {
              if (app.Properties.ContainsKey("Transaction"))
                {
                    Transaction.Current = (Transaction)app.Properties["Transaction"];
                }

                var invoke = next.Invoke();

                if (app.Properties.ContainsKey("Transaction"))
                {
                    Transaction.Current = null;
                }

                return invoke;
            });

        }))
        {
          //Your test code
        });