【问题标题】:Testing JSON API in Rails 3.2 using rspec using exact PUT/POST bodies as Backbone would send在 Rails 3.2 中使用 rspec 测试 JSON API,使用精确的 PUT/POST 主体,因为 Backbone 将发送
【发布时间】:2012-09-11 22:48:03
【问题描述】:

我正在尝试为使用 Rails 3.2 编写的 JSON API 编写一组 rspec 测试,其中 Backbone 作为前端。我正在编写的测试专门针对 Rails 控制器。

现在,应用程序本身运行良好。当客户端发出带有正文的 PUT 请求时:

{
  "id":1,
  "name":"updated product set",
  ...
}

一切都很棒。在后台,Rails 将获取该主体,然后将其转换为:

{
  "id":1,
  "name":"updated product set",
  ...
  "model_name" => { ... }
}

哈希“model_name”指向的位置包含它可以从输入中自动计算出的属性值。一切都很好。

当我从测试环境尝试相同的确切请求时,一切都不好。如果我创建的哈希与上面的 PUT 正文哈希完全相同,但在 rspec 中:

@update_json = {
  "id":1,
  "name":"updated product set",
  ...
}
header "Accept","application/json"
header "Content-type","application/json"
put :update, @update_json

事情根本没有解决。在控制器中,如果我检查 params 变量,我会得到:

{ "model_name" => {} }

如果我省略了“Content-type”标题行,我会得到@update_json,但没有Rails 操作来创建我在控制器中需要的“model_name”映射。

我成功运行测试的唯一方法是:

@update_json = {
  :format => "json",
  "id":1,
  "model_name" => {
      "id":1,
      "name":"updated product set",
      ...
  }
}
header "Accept","application/json"
put :update, @update_json

但是,这不是真实世界的测试,因为它没有测试将由我的骨干前端发送的确切 PUT 正文。

有什么想法吗?

更新: 环顾四周看起来,您实际上无法从 rspec 发出真正的 HTTP 请求;它只是模拟出来的。例如,您无法让系统以 404 响应,因为 Rails 抛出了一个异常,该异常通常会被 Rails 网络堆栈捕获并变成 404,但在 Rspec 中没有。所以问题看起来比上面的更深......

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 backbone.js


    【解决方案1】:

    看起来post :update, '{"some": "json"}' 的功能已添加到此提交中 rspec 使用的内部 ActionPack test_case.rb 中: https://github.com/rails/rails/commit/5b9708840f4cc1d5414c64be43c5fc6b51d4ecbf

    因此,其他选项可能是升级到 Rails 4,一切都会按预期进行,或者集成上述提交。

    【讨论】:

      【解决方案2】:

      我遇到了同样的问题。无论我做了什么,或者我以哪种方式将内容类型指定为“应用程序/json”,它都不起作用。如果网上有关于将内容类型设置为 json 的建议,我试了一下。我什至同时尝试了它们。

      最终,我追踪到了 ActionController::ParamsWrapper,_wrapper_enabled 在哪里?总是返回 false(由于 request.content_mime_type 为 nil)。这个解决方案对我有用。我一直在寻找要添加的“神奇”参数键,并且这样做了。

      mime_type = mock
      mime_type.stub :ref => :json
      request.stub :content_mime_type => mime_type
      request.accept = 'application/json'
      post :create, widget.as_json
      

      值是:

      widget.as_json #=> {
        "created_at"=>nil,
        "description"=>"Description 1 - Quidem nihil quae aliquid sed qui.",
        "id"=>nil,
        "order"=>1,
        "title"=>"Title 1 - ut",
        "updated_at"=>nil
      }
      
      # params hash in the controller.
      params #=> {
        "created_at"=>nil,
        "description"=>"Description 1 - Quidem nihil quae aliquid sed qui.",
        "id"=>nil,
        "order"=>"1",
        "title"=>"Title 1 - ut",
        "updated_at"=>nil,
        "controller"=>"api/widgets",
        "action"=>"create",
        "widget"=>{
          "title"=>"Title 1 - ut",
          "order"=>"1",
          "description"=>"Description 1 - Quidem nihil quae aliquid sed qui."
        }
      }
      

      这正是我想要的。只有标题、顺序和描述被设置为 attr_accessible,因此只有出现在神奇创建的 :widget 哈希中的属性。

      我也在使用 active_model_serializers,所以 as_json 正在运行,以防有人认为这很重要。

      这是我正在构建的公共示例应用程序的一部分,因此如果有人认为它可能有用,则可以在使用中看到此代码。

      【讨论】:

      • 这行得通,而且比我们创建的破解的 wrap_params 测试方法要好得多 :) 谢谢!!
      【解决方案3】:

      你可以试试这个吗?

      @update_json = {
        "id":1,
        "model_name" => {
            "id":1,
            "name":"updated product set",
            ...
        }
      }
      put :update, @update_json, :format => :json
      

      编辑(2012 年 11 月 11 日):

      您是否尝试过手动实例化请求并查看会发生什么?

      很奇怪。您是否尝试过“普通的 Ruby 方式”?

      env = Rack::MockRequest.env_for('/posts/1', :method => 'PUT', <some other params>)
      status, headers, body = PostsController.action(:update).call(env)
      ...
      

      【讨论】:

      • 塞萨里奥:是的。和上面一样的问题。我认为根本问题是这种风格的集成测试在 rspec 中是不可能的,因为它不像外部请求那样通过 Rack。
      • 更新答案,把内联代码放在这里是一个 PITA :)
      • Cesario:我没试过,但这是个好主意。但是,不是 put/get/etc。 rspec 词汇表使用下面的 MockRequest 吗?我怀疑这是同一个问题,也就是说 Rack::MockRequest 避免了网络堆栈。会试一试,看看我是否发现有什么不同。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-18
      • 1970-01-01
      • 2018-01-02
      • 2013-09-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多