如何在模型上模拟Rails视图测试的特定属性?

时间:2014-10-16 09:44:30

标签: ruby-on-rails ruby rspec mocking null-object-pattern

我正在为rails视图编写测试,假设视图类似于:

show.json.rep

r.element :user, @user do |u|
    r.element :id, u.id
    r.element :somefield1, u.somefield1
    // a lot of fields here
    r.element :somefield100, u.somefield100
end

现在我想测试它生成的json,并且只关注id字段。

如果我的测试代码写得像:

describe "show.json.rep" do
   it "will generate json with correct id" do
       assign(:user, mock(:user, :id=>111))
       render
       puts "######### generate json:"
       puts rendered
       ...
   end
end

它会报告这样的错误:

Failure/Error: render
     ActionView::Template::Error:
       Mock :user received unexpected message :somefield1 with (no args)

我不想模仿我感兴趣的所有字段somefieldX,所以我尝试了as_null_object

describe "show.json.rep" do
   it "will generate json with correct id" do
       assign(:user, mock(:user, :id=>111).as_null_object)
       render
       puts "######### generate json:"
       puts rendered
       ...
   end
end

这一次,它没有报告该错误,但奇怪的是,rendered值为null !!

######### generate json:
null

我不确定为什么以及如何修复它?或者还有其他方法可以让我提供我感兴趣的领域吗?

1 个答案:

答案 0 :(得分:0)

在创建对象时设置id,然后调用as_null_object将导致id(和任何其他方法)返回nil。

  

使用as_null_object方法忽略任何不是的消息   明确地设置为存根或消息期望。

这就是你如何存根id方法:

require 'json'

describe "show.json.rep" do

   let(:user) { double("User").as_null_object }
   let(:json) { JSON.parse(rendered).symbolize_keys! }

   before(:each) do
     allow(user).to receive(:id).and_return(666)
     assign(:user, user)
     render
   end

   it "will generate json with correct id" do
       expect(json[:id]).to equal (user.id)
   end
end

但从长远来看,你可能应该使用fixturesfactories,而不是在整个测试中设置双打。 我也更喜欢使用ActiveModel serializers,因为它们更容易,更快速,因为你没有编码和解析JSON。

修改

另一种解决方案是使用User.new

let(:user) { User.new(id: 666) }