如何使类对象实例返回预定义的值?

时间:2011-09-28 22:02:34

标签: ruby-on-rails ruby ruby-on-rails-3 rspec rspec2

我正在使用Ruby on Rails 3.1.0和rspec-rails 2 gem。我正在测试我的控制器代码(BTW:我是rspec的新手),我想让类对象实例返回预定义的值。也就是说,在我的控制器中我有:

def create
  ...

  if @current_user.has_authorization?
    ...
  else
    ...
  end
end

为了测试else语句的“if部分”,我想使其成为可能(对于我正在处理的当前规范示例 - 请参阅下面的示例实现) @current_user.has_authorization?会返回false

我该怎么做?


我在我的spec文件中尝试了以下内容,但似乎无法正常工作:

it "should have no authorization" do
  @current_user.stub(:has_authorization?).and_return(false)

  # I also tried the following and it still doesn't work
  # @current_user.should_receive(:has_authorization?).and_return(false)

  post :create
  ...
end

3 个答案:

答案 0 :(得分:1)

在您的rspec测试的上下文中,

@current_user与控制器上下文中的@current_user不同。一个是实例变量,在Rails运行的控制器类的实例中。另一个是rspec测试中的实例变量。

你不应该捅你的用户变量,而是需要这样做,以便Rails找到测试框架提供的用户。看看this example

答案 1 :(得分:0)

要避免此问题,您可以使用mocha,为此,请执行以下操作:

将mocha gem添加到Gemfile并运行bundle install

然后更改spec_helper.rb文件

中的Rspec模拟配置框架
RSpec.configure do |config|
  config.mock_with :mocha
  # config.mock_with :rspec
end

然后在您的规范中,您可以执行此操作

it "should have no authorization" do
  User.any_instance.stubs(:has_authorization?).returns(false)
  post :create
  ...
end

此(或the correct answer from Coderer)将解决您的问题。

请注意,据我所知,Rspec模拟函数中没有any_instance等效项。

答案 2 :(得分:0)

当您的规范正在运行时,self指向一个测试对象(在某个时间内在规范中尝试p selfputs self.class并自行查看),因此@current_user是引用该测试对象上的实例变量。它与控制器上的@current_user实例变量没有任何关系。

执行所需操作的一种方法是在控制器上创建current_user 方法访问者,然后调用它而不是直接访问@current_user。然后,您可以从规范中存根或模拟该方法,假设您可以获得指向控制器实例的指针。

另一种方法是直接从规范中设置@current_user变量。再次,获取指向您的控制器实例的指针,然后执行x = mock("user"); controller.instance_variable_set(:@current_user, x),然后您可以在x上模拟/存根方法。