尽管存在茬,但Double收到了意外的消息

时间:2014-11-03 12:40:25

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

尝试运行以下规范时报告

Double received unexpected message失败/错误:

MyKlass
  does something
  does something again (FAILED - 1)

Failures:

  1) MyKlass does something again
     Failure/Error: MyKlass.do_something
       Double "OtherKlass" received unexpected message :closed? with (no args)
     # ./lib/my_klass.rb:5:in `do_something'
     # ./spec/my_klass_spec.rb:17:in `block (2 levels) in <top (required)>'

Finished in 2.05 seconds
2 examples, 1 failure

Failed examples:

rspec ./spec/my_klass_spec.rb:16 # MyKlass does something again

以下是轻松复制此问题的最小示例...

规范文件spec/my_klass_spec.rb

 1 require "spec_helper"
 2
 3 class OtherKlass; end
 4 
 5 describe MyKlass do
 6   let(:objekt) { double("OtherKlass", closed?: "NOT REALLY") }
 7 
 8   before :each do
 9     OtherKlass.stub(:get_objekt).and_return(objekt)
10   end
11 
12   it "does something" do
13     MyKlass.do_something
14   end
15 
16   it "does something again" do
17     MyKlass.do_something
18     MyKlass.do_something
19   end
20 end

代码lib/my_klass.rb

1 class MyKlass
2   @@klass_var = nil
3 
4   def self.do_something
5     if @@klass_var.blank? || @@klass_var.closed?
6       @@klass_var ||= OtherKlass.get_objekt
7     end
8   end
9 end

我无法理解为什么closed?被报告为意外消息,当它在第6行的规范文件中存根时。

非常感谢您的协助!

2 个答案:

答案 0 :(得分:1)

在RSpec 3中,您可以使用class_double,它允许您创建一个类的双精度。结合as_stubbed_const,您可以替换类的原始实现:

RSpec.describe MyKlass do
  let(:objekt) do
    double(OtherKlass, closed?: 'NOT REALLY')
  end

  before do
    class_double(OtherKlass, get_objekt: objekt).as_stubbed_const
  end

  it 'does something' do
    MyKlass.do_something
  end
end

在Rspec 2中,以下内容应该有效:

RSpec.describe MyKlass do
  let(:objekt) do
    double('OtherKlass', closed?: 'NOT REALLY')
  end

  before do
    fake_klass = Class.new
    fake_klass.stub(:get_objekt) { objekt }
    stub_const('OtherKlass', fake_klass)
  end

  it 'does something' do
    MyKlass.do_something
  end
end

答案 1 :(得分:0)

在每个测试解决问题之前显式设置类变量:

before(:each) do
  MyKlass.class_variable_set :@@klass_var, nil
end

可能有人可以找到更好的解决方案,但是这个解决方案对我有用。