【问题标题】:Rack::Test PUT method with JSON fails to convert JSON to params带有 JSON 的 Rack::Test PUT 方法无法将 JSON 转换为参数
【发布时间】:2012-01-25 19:58:35
【问题描述】:

我目前正在使用 rails 3.1.3、cucumber-rails 1.2.1、rspec-rails 2.8.1 和 json_spec 0.8.0。我正在构建一个将由 Android 应用程序使用的宁静 Web 服务 API。我正在使用 TDD / BDD 实践,并且能够在我的 Cucumber 步骤定义中使用 get() 和 post() 成功测试 Web 服务操作。但是,在使用 put() 时,我遇到了问题。

这是我的 device_update.feature:

Feature: Updating a Device
  The web service should accept a PUT request to update device settings.

  Scenario: The device information is updated when valid data is posted to the web service.
    Given a device exists
    When I put "/services/devices/4A3CABD4C4DE6E9F.json" with:
      """
      {
        "device": {
          "carrier": "SPRINT"
        }
      }
      """    
    Then the JSON should be:
      """
      {
        "message": "Device updated.",
        "response_code": 1
      }
      """

我的步骤定义是:

When /^I get "([^"]*)"$/ do |path|
  get(path)
end

When /^I post to "([^"]*)" with:$/ do |path, json_string|
  post(path, json_string, {"CONTENT_TYPE" => "application/json"})
end

When /^I put "([^"]*)" with:$/ do |path, json_string|
  put(path, json_string, {"CONTENT_TYPE" => "application/json"})
end

运行测试时,我得到以下信息:

When I put "/services/devices/4A3CABD4C4DE6E9F.json" with:
  """
  {
    "device": {
      "carrier": "SPRINT"
    }
  }
  """
  You have a nil object when you didn't expect it!
  You might have expected an instance of Array.
  The error occurred while evaluating nil.[] (NoMethodError)
  ./app/controllers/services/devices_controller.rb:75:in `update'
  ./features/step_definitions/request_steps.rb:10:in `/^I put "([^"]*)" with:$/'
  features/services/devices/device_update.feature:7:in `When I put "/services/devices/4A3CABD4C4DE6E9F.json" with:'
Then the JSON should be:
  """
  {
    "message": "Device updated.",
    "response_code": 1
  }
  """

当我查看日志时,我看到以下内容:

Started PUT "/services/devices/4A3CABD4C4DE6E98.json" for 127.0.0.1 at 2012-01-25 11:36:16 -0800
Processing by Services::DevicesController#update as JSON
Parameters: {"{\n  \"device\": {\n    \"carrier\": "SPRINT"\n  }\n}"=>nil, "id"=>"4A3CABD4C4DE6E98"}

我截断了活动记录调用,因为它们不相关。很明显,JSON 没有被转换为正确的参数,这就是为什么我得到一个意外的 nil。

对如何进行这项工作有任何想法吗?

【问题讨论】:

    标签: ruby-on-rails-3 testing rest cucumber rspec-rails


    【解决方案1】:

    您不应将字符串传递给put。它负责转换为 JSON 字符串,这通常是一件好事。这里发生的是您的 JSON 字符串再次被 putJSONified

    您应该先解析 JSON 字符串并将结果对象传递给put

    When /^I put "([^"]*)" with:$/ do |path, json_string|
      payload = JSON.parse(json_string)
      put(path, payload, {"CONTENT_TYPE" => "application/json"})
    end
    

    另外,可能不需要内容类型。

    【讨论】:

    • 我很好奇为什么当 post() 像这样正常工作时我需要使用 put() 这种方法:When /^I post to "([^"]*)" with:$/ do |path, json_string| post(path, json_string, {"CONTENT_TYPE" => "application/json"}) end rack-test 中的两种方法似乎在做同样的事情, 但是 JSON 会在 post() 中自动解析而不是 put()?
    • 我不太清楚,但我认为这与 Rack 如何处理请求及其内容有关。
    • 它可以工作,但我并没有真正测试应用程序通过 PUT 接受 JSON 代码的能力。到目前为止,我的解决方案只是重写路由,以便它们使用 POST 代替 PUT 和 DELETE。不是最好的,但更容易测试。
    猜你喜欢
    • 2014-07-10
    • 2013-03-13
    • 2021-05-17
    • 2016-05-26
    • 1970-01-01
    • 1970-01-01
    • 2022-11-16
    • 2016-07-25
    • 2019-06-17
    相关资源
    最近更新 更多