Ruby on rails 3 如何使用Mocha和rspec测试模型错误?
我有一个与Mocha测试模型错误相关的问题:Ruby on rails 3 如何使用Mocha和rspec测试模型错误?,ruby-on-rails-3,rspec,mocha.js,rails-models,Ruby On Rails 3,Rspec,Mocha.js,Rails Models,我有一个与Mocha测试模型错误相关的问题: 这是我的控制器(Api/艺术家控制器): 当我运行测试时,这是我在上述测试中得到的错误: Failure/Error: post :create, :format => :json NoMethodError: undefined method `add_on_blank' for {}:Hash # ./app/controllers/api/artists_controller.rb:17:in `cre
Failure/Error: post :create, :format => :json
NoMethodError:
undefined method `add_on_blank' for {}:Hash
# ./app/controllers/api/artists_controller.rb:17:in `create'
# ./spec/controllers/api/artists_controller_spec.rb:56:in `block (3 levels) in <top (required)>'
失败/错误:post:create,:format=>:json
命名错误:
{}的未定义方法“add_on_blank”:哈希
#/app/controllers/api/artists\u controller.rb:17:in'create'
#./spec/controllers/api/artists\u controller\u spec.rb:56:in'block(3层)in'
我开始使用Mocha,所以当我想测试重复名称的验证时,我不知道是否有办法测试特定情况下的json结果。ActiveRecord::Base#errors
(即Artist#errors
)不是简单的散列。它应该是ActiveModel::Errors
的一个实例。您正在使用散列对其进行存根,ActiveRecord试图在其上调用add\u\u blank
,但失败了
我不认为save
调用是有效的吗?
,我怀疑它正在运行验证,然后试图调用add\u on\u blank
来追加错误,但由于您已经将错误
剔除,所以失败了
这并不是测试控制器的好方法。它对Artist
的内部结构做了太多的假设。您还测试了根本不属于控制器的东西<代码>错误未在操作中的任何位置引用。在控制器中唯一值得测试的行为是它是否创建了一个艺术家
;如果该Artist
未能保存,则它将使用它呈现JSON;如果保存成功,它将重定向。这是控制员的全部责任
如果要测试错误是否以某种方式呈现,则应编写单独的视图规范。如果要测试缺少的字段是否会生成错误,则应编写模型规范。如果不想编写视图规范,则依赖模型来填充错误
(在模型规范中测试),在控制器中,只需测试render
是否使用json
调用,并将Artist
实例设置为
一般来说,最好避免尽可能多的顽固,但在这种情况下,我唯一考虑的是“代码>艺术家”。新< /COD>返回模拟,而<代码>保存< /代码>在模拟中返回假。然后我会检查,以确保它与模拟渲染
更简单的选择是只创建一个实际的Artist
记录,然后使用重复的参数调用post
,以触发验证失败。不利的一面是,您会访问数据库,在控制器规范中避免访问数据库是值得称赞的,但通常更方便。如果您希望在控制器规范中避免DB命中,可以在Capybara特性规范中这样做
如果您想尝试测试自己的方式,您可以手动创建ActiveModel::Errors
的实例并填充该实例,或者在其上填充存根方法,然后将Artist.any_instance.stubs(:Errors)
存根(:Errors)
以返回具有ActiveModel::Errors
兼容行为的模拟,但这是一个很大的模拟
最后一个提示:不要使用post:create,:format=>:json
。使用xhr:post,:create
生成真正的Ajax请求,而不是依赖格式
参数。这是对您的路由和响应代码的一个更可靠的测试。如何回答“您不应该这样做”的问题?
class Artist < ActiveRecord::Base
include Core::BaseModel
attr_accessible :name
has_many :albums
validates :name, :presence=>true, :uniqueness=>{:case_sensitive=> false}
default_scope where :deleted=>false
end
it "should not save a duplicated artist" do
Artist.any_instance.stubs(:is_valid?).returns(false)
Artist.any_instance.stubs(:errors).returns({:name=>[I18n.t('activerecord.errors.messages.taken')]})
post :create, :format => :json
expect(response).not_to be_success
expect(response.code).to eq("422")
results = JSON.parse(response.body)
expect(results).to include({
"errors"=>{
"name"=>[I18n.t('activerecord.errors.messages.taken')]
}
})
end
Failure/Error: post :create, :format => :json
NoMethodError:
undefined method `add_on_blank' for {}:Hash
# ./app/controllers/api/artists_controller.rb:17:in `create'
# ./spec/controllers/api/artists_controller_spec.rb:56:in `block (3 levels) in <top (required)>'