如何对JSON控制器进行单元测试?

Yar*_*veh 25 ruby ruby-on-rails

这是我的行动:

def my_action
  str = ... # get json str somehow  
  render :json => str
end
Run Code Online (Sandbox Code Playgroud)

这是我的测试:

test "my test" do 
  post(:my_action, {'param' => "value"}    
  assert_response :success
end
Run Code Online (Sandbox Code Playgroud)

我想添加另一个断言,即发出的JSON包含一些值.如何在控制器单元测试中完成,而不是通过解析视图结果?

Sim*_*eev 51

就像上面评论过的人一样,这将是一次功能测试.

最好的方法可能是发出请求,解析JSON响应主体,并将其与预期结果相匹配.

如果我companies_controller使用FactoryGirl在Rspec中:

describe "GET 'show'" do

  before(:each) do
    @company = Factory(:company)
    get 'show', :format => :json, :id => @company.id
  end

  it "should be successful" do
     response.should be_success
  end

  it "should return the correct company when correct id is passed" do
    body = JSON.parse(response.body)
    body["id"].should == @company.id
  end

end
Run Code Online (Sandbox Code Playgroud)

您可以以相同的方式测试其他属性.此外,我通常有invalid上下文,我会尝试传递无效参数.


ken*_*ill 20

使用Rails的内置功能测试:

require 'test_helper'

class ZombiesControllerTest < ActionController::TestCase

  setup do
    @request.headers['Accept'] = Mime::JSON
    @request.headers['Content-Type'] = Mime::JSON.to_s

  end

  test "should post my action" do
    post :my_action, { 'param' => "value" }, :format => "json"
    assert_response :success
    body = JSON.parse(response.body)
    assert_equal "Some returned value", body["str"]
  end

end
Run Code Online (Sandbox Code Playgroud)


jos*_*ipp 6

这个控制器测试对我使用 Minitest 和 Rails 4.2.4 效果很好:

require 'test_helper'

class ThingsControllerTest < ActionController::TestCase

  test "should successfully create a new thing" do
    assert_difference 'Thing.count' do
      @request.headers["Accept"] = "application/json"

      post(:create, {thing: {name: "My Thing"}})
    end

    assert_response :success

    json_response = JSON.parse(@response.body)
    assert_equal json_response["name"], "My Thing"
  end

end
Run Code Online (Sandbox Code Playgroud)

这以集成测试的形式工作。

require 'test_helper'

class ThingsRequestsTest < ActionDispatch::IntegrationTest

  test "creates new thing" do
    assert_difference 'Thing.count' do
      post("/things.json", {thing: { name: "My Thing"}})
    end

    assert_equal 201, status

    json_response = JSON.parse(@response.body)
    assert_equal json_response["name"], "My Thing"
  end

end
Run Code Online (Sandbox Code Playgroud)

老实说,试图将语法上的细微差别直接从一种类型的测试保持在另一种类型的测试中是很奇怪的。

  • 在 Rails 6 中,我们可以使用 `response.parsed_body` 而不是 `JSON.parse(response.body)`。 (3认同)