Ruby on rails 3 如何使用Mocha和rspec测试模型错误?

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

我有一个与Mocha测试模型错误相关的问题:

  • 这是我的控制器(Api/艺术家控制器):

  • 当我运行测试时,这是我在上述测试中得到的错误:

    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)>'