WebAPI和事务的集成测试

时间:2015-04-30 11:49:26

标签: rest asp.net-web-api transactions

我有一个面向ASP.NET Web API的客户端,它既有直接的SQL服务器调用,也有调用其他 ASP.NET Web API来执行数据操作。我想对客户端REST API 进行端到端集成测试,以测试其他被调用REST API的路由以及各种数据操作是否成功。

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

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

REST API的事务操作是否可行,欢迎任何有关Integration测试的建议。我在Visual Studio 2013环境中使用NUNIT。

2 个答案:

答案 0 :(得分:2)

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

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

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

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

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

我们这样做的原因是Web API需要托管在某个地方进行端到端的测试,单元测试会在签到时立即捕获大部分错误 - 以及每次检查时启动虚拟机的每晚相关路由如果你有几个开发人员整天定期检查,这是很昂贵的。这确实涵盖了大多数方面,但正如我所说,不是100%理想。

答案 1 :(得分:1)

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

将当前事务添加到TestServer。将请求发送到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
        });