1

好的,所以我的主要问题是我已经在我们的项目中实现了 Mailboxer 来处理消息传递,并且我正在尝试为它编写测试。然而,我一次又一次地跌跌撞撞。我尝试了几种不同的存根/模拟,但没有取得任何进展。

我们有一个依赖于 before_filters 的 conversations_controller.rb 来设置执行每个操作所需的所有实例变量。然后在控制器动作中,直接引用实例变量来执行任何类型的动作或返回特定数据。

下面是我们的索引操作的示例,它返回在 before_filter 中指定的“框”中的所有对话,邮箱也在另一个 before_filter 中指定:

class ConversationsController < ::ApplicationController
    before_filter :get_user_mailbox, only: [:index, :new_message, :show_message, :mark_as_read, :mark_as_unread, :create_message, :reply_message, :update, :destroy_message, :untrash]
    before_filter :get_box

    def index
      if @box.eql? "inbox"
        @conversations = @mailbox.inbox
      elsif @box.eql? "sentbox"
        @conversations = @mailbox.sentbox
      else
        @conversations = @mailbox.trash
      end
    end

在过滤器之前:

private
def get_user_mailbox
    @user = User.where(:user_name => user.user_name.downcase).where(:email => user.email.downcase).first_or_create
    @mailbox = @user.mailbox if @user
end

def get_box
    if params[:box].blank? or !["inbox","sentbox","trash"].include?params[:box]
      params[:box] = 'inbox'
    end
    @box = params[:box]
end

所以我想我有两个问题合二为一。首先,如何让我的测试生成索引操作所需的正确数据@mailbox、@user 和@box。接下来,我如何传递 fake 参数以将 @box 设置为不同的“inbox/sentbox/trash”。我已经尝试过 controller.index({box: "inbox"}) 但总是收到“错误的参数 1 for 0”消息。

我以各种不同的方式尝试了以下方法,但总是得到 nil:class 错误,这意味着我的实例变量肯定没有正确设置。

describe "GET 'index' returns correct mailbox box" do
  before :each do
    @user = User.where(:user_name => 'test').where(:email => 'test@test.com').first_or_create
    @mailbox = @user.mailbox
  end

  it "#index returns inbox when box = 'inbox'" do
    mock_model User
    User.stub_chain(:where, :where).and_return(@user)
    controller.index.should == @mailbox.inbox
  end
end
4

2 回答 2

0

过滤器和回调很难测试和调试。尽可能避免它们。

在这种情况下,我认为您before_filter没有必要,因此无需对其进行测试。这些方法更好的归宿是模型。

检查我的重构:

class User < ActiveRecord::Base
  delegate :inbox, :sentbox, :trash, to: :mailbox
end

class ConversationsController < ::ApplicationController
  def index
    @conversations = current_user.send get_box
  end

  private
  def get_box
    # your code
  end
end

就这样。应该够了。

然后,您可以定期测试。

于 2013-08-20T14:48:28.420 回答
0

首先,阅读Rails 测试的官方文档:使用数据进行测试并将参数传递给控制器​​。

要为您的测试生成数据,您可以:

  1. 使用 Rails 固定装置或使用类似 factory girl 之类的邮箱和用户填充您的测试数据库

  2. 使用模拟对象来伪造数据。我个人使用摩卡宝石,但还有其他的

我倾向于将两者结合使用,在可能的情况下更喜欢模拟对象,而在模拟需要太多代码时回退到工厂女孩。

于 2013-08-20T15:01:00.537 回答