1

我正在为 rails 视图编写测试,可以说视图类似于:

显示.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

我不确定为什么以及如何解决它?或者有没有其他方法让我只提供我感兴趣的领域?

4

1 回答 1

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

但从长远来看,您可能应该使用固定装置工厂,而不是在整个测试中设置双打。我也更喜欢使用ActiveModel 序列化程序,因为它们更容易和更快地测试,因为你没有编码和解析 JSON。

编辑:

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

let(:user) { User.new(id: 666) }
于 2014-10-16T10:26:53.633 回答