如何对JSON控制器进行单元测试?
这是我的行动:如何对JSON控制器进行单元测试?
def my_action
str = ... # get json str somehow
render :json => str
end
这是我的测试:
test "my test" do
post(:my_action, {'param' => "value"}
assert_response :success
end
我想补充的另一个说法,即发出JSON包含一定的价值。我怎么能在控制器单元测试中做到这一点,而不是通过解析视图结果?
就像人们上面评论的一样,这将是一个功能测试。
最好的方法可能是发出请求,解析JSON响应正文,并将其与预期结果进行匹配。
如果我使用FactoryGirl有companies_controller
在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
您可以测试其他属性相同的方式。此外,我通常有invalid
上下文,我会尝试传递无效的参数。
使用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
当你有一个respond_to函数可以返回基于不同块的不同数据时,这个方法就行得通了。在上面的例子中,海报定义了REQUEST发送到控制器的方法,以触发正确的respond_to块。 – FlyingV
我对这种做法略有不同,如果我使用的Jbuilder
的宝石,现在可以从Rails的团队。 (这种方法适用于其他可以使JSON或XML作为视图的宝石。)我更喜欢在功能测试中尽可能进行单元测试,因为它们可以快得多。使用Jbuilder,您可以将大部分测试转换为单元测试。
是的,你仍然有控制器的功能测试,但有很少的,他们不解析JSON。功能测试仅测试控制器逻辑,而不是渲染的JSON。一个有效的请求可能断言以下(RSpec的)功能测试:
assert_response :success
expect(response).to render_template(:show)
expect(assigns(:item).id).to eq(expected_item.id)
我只是验证它是成功的,它呈现模板,并将其传递的项目模板。此时,视图具有所需的信息来进行适当的渲染。
现在测试单元测试Jbuilder视图呈现的JSON。
describe 'api/v1/items/show.json.jbuilder' do
it 'includes foo' do
assign(:item, account.build(foo: 'bar'))
render
json = JSON.parse(rendered)
expect(json['item']['foo']).to eq('bar')
end
# A bunch of other JSON tests...
该控制器的测试工作很适合我使用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
而且这个工作在集成测试的形式。
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
老实说,试图将语法上的细微差别从一种测试类型转变为另一种测试类型是很奇怪的。
不会解析json响应是最简单的方法吗? – jdeseno
我的印象是单元测试实际上并没有调用视图。是这样吗?如果是,哪种测试是我所寻找的(查看?) –
我相信这个问题已经讨论过[这里](http://stackoverflow.com/questions/336716/how-to-test-json-result-from -rails官能检验)。你在做什么不是单位,而是功能测试。它实际上呈现了这个视图。 –