修改 编辑改为关于测试而不是代码的问题,因为我看到应用程序行为正确。
我正在编写一个Rails 3应用程序,它纯粹是一个RESTful Web服务(即没有视图)。我有一个用户模型,用户名是unqiue
class User < ActiveRecord::Base
validates_uniqueness_of :username
end
在我的控制器中,我有以下代码来处理正在创建的新用户:
def create
@user = User.new(ActiveSupport::JSON.decode(request.raw_post))
if @user.save
puts "Added user #{@user.username}"
format.json { render :json => "" }
else
puts "Failed to add user: #{@user.errors.to_json}"
render json: @user.errors, status: :unprocessable_entity
end
end
然后我进行了一项功能测试,创建了一个与现有用户具有相同用户名的用户:
test "should not create user with duplicate username" do
@jim = users(:jim)
post '/users', @jim.to_json, "CONTENT_TYPE" => "application/json"
assert_response :unprocessable_entity
end
当我运行测试时,控制器输出“无法添加用户:{”用户名“:[”已被采用“]}”按预期方式,但测试失败: 预期的响应是&lt;:unprocessable_entity&gt;,但是&lt; 200&gt;
然而,随着卷曲,我得到了我期望的回应:
curl -i -X POST -d '{"username": "james", "email": "test@test.com" }'
HTTP/1.1 422
{"username":["has already been taken"]}
那么我在测试中的断言在哪里出错?
答案 0 :(得分:0)
您可能应该使用respond_with
。它将处理许多REST逻辑,包括设置状态代码。
此外,对于只是REST服务的应用程序,Rails可能过度。您可能想要考虑Sinatra。
答案 1 :(得分:0)
原因是我转而使用RackTest来允许我在正文中发布JSON(即不作为表单参数。)因此,我应该在last_response上做出断言(RackTest MockResponse用于后调用)而不是使用assert_response:
test "should not create user with duplicate username" do
@jim = users(:jim)
post '/users.json', @jim.to_json, "CONTENT_TYPE" => "application/json"
assert_status :unprocessable_entity
end
def assert_status(expected_status)
assert_equal last_response.status, Rack::Utils.status_code(expected_status)
end
我很惊讶assert_response:当没有调用任何方法为@response产生值时成功通过。如果该断言失败,或者抛出异常,那么追踪我的错误就更容易了,但是请大家好看!