0

我的模型:

class Post < ActiveRecord::Base
 #...
 def my_method
   {:created_at => self.created_at, :words => self.text.split.find_by{/*my_conditiond_here*/}}
 end
 #...
end

控制器:

class TasksController < ApplicationController
 #...
 def my_action
   posts = Post.where(params[:conditions])
   @words = posts.map{|post| post.my_method}.flatten
 end
 #...
end

但是当我尝试对其进行测试时,我遇到了一些麻烦。

it "returns words for single post" do
  post = FactoryGirl.create :post, :text => 'any text here'
  get :my_action
  expect(assigns[:words]).to eq(post.my_method)
end

我得到类似的东西:

   expected: [{:words=>["any", "text", "here"], :created_at=>2013-11-12 09:33:04 UTC}]
        got: [{"words"=>["any", "text", "here"], "created_at"=>2013-11-12 09:33:04 UTC}]

不仅如此,如果我使用

  expect(assigns[:words].first).to eq(post.my_method.fitst.with_indifferent_access)

它失败:

   expected: {"words"=>["any", "text", "here"], "created_at"=>2013-11-12 09:33:04 UTC}
        got: {"words"=>["any", "text", "here"], "created_at"=>2013-11-12 09:33:04 UTC}
   (compared using ==)

   Diff:

通过实验,我意识到了这个问题created_at元素中的问题。

看起来可以存根my_method,但我不知道如何返回连接到对象的值。例如身份证。或者建议请更好的测试方法my_action

4

1 回答 1

0

我会执行以下任一操作,但更倾向于第二种解决方案(消息期望):

  1. 仅检查words数组,而不是时间戳,例如created_at.
  2. Post::where将所有和#map调用封装到 上的描述性类/单例方法中Post,并检查是否Post接收到正确的消息。这样,您只检查是否将正确的消息传递给 Post,而不是同时测试 Post 和控制器。

换句话说,对于上面的解决方案 #2,您可能会遇到这样的情况:

post.rb:

class Post
  def self.posts_with_my_method params
    # move code from controller here
  end
end

任务控制器.rb:

class TasksController < ApplicationController
 #...
  def my_action
    @words = Post.posts_with_my_method params(params)
  end
  #...
 end

规格:

it "returns words for single post" do
  Post.should_receive(:posts_with_my_method).and_return([:foo])
  get :my_action
  expect(assigns[:words]).to eq([:foo])
end
于 2013-11-13T14:37:31.310 回答