无法在RSpec / Rails中存根类方法(并在存根上使用动态返回)

时间:2012-05-10 04:02:17

标签: ruby-on-rails testing rspec mocking stubbing

晚上好,

我正在尝试在我的“Simulation”类中测试一个相当长的方法,该类调用类方法“is_male_alive?”和“is_female_alive?”在我的“年龄”课上几百次。这些类方法的返回值基于统计信息,我想将它们存根以返回特定值,以便我的测试每次都运行相同。

Age.rb:

...

def is_male_alive?(age)
  return false if age > 119
  if (age < 0 || age == nil || age == "")
    return false
  end    
  death_prob = grab_probability_male(age)
  rand_value = rand
  rand_value > death_prob
end

...

(女性版本与一些不同的常量基本相同)

在我的“模拟”课程中,我执行以下操作:

def single_simulation_run

  ...
  male_alive = Age.is_male_alive?(male_age_array[0])
  female_alive = Age.is_female_alive?(female_age_array[0])
  ...
end

在模拟的每次迭代中 - 基本上它只传递一个年龄(例如is_male_alive?(56))并返回true或false。

我想将这两种方法排除在外:

  1. is_male_alive?对于小于75的任何参数,返回true,否则返回
  2. is_female_alive?对于小于80的任何参数,返回true,否则返回
  3. 我已经尝试过以下内容,看看我是否有能力将其存根(simulation_spec.rb):

    Age.should_receive(:is_male_alive?).exactly(89).times
    results = @sim.send("generate_asset_performance")
    

    但是我收到以下错误:

     Failure/Error: Age.should_receive(:is_male_alive?).exactly(89).times
       (<Age(id: integer, age: integer, male_prob: decimal, female_prob: decimal) (class)>).is_male_alive?(any args)
           expected: 89 times
           received: 0 times
    

    我也不知道如何设置它以便根据参数动态生成存根返回值。有没有办法用proc做到这一点?

    有没有办法模拟整个Age类(而不是仅仅模拟Age类的单个实例?)

    感谢您的帮助!!

    更新1

    看起来调用此方法存在问题......这实在令人困惑。为了真正看到它是否被调用,我在方法中抛出了“引发ArgumentError”。

    开发环境(控制台):

    1.9.3p125 :003 > sim = Simulation.last
    1.9.3p125 :004 > sim.generate_results
      --->  ArgumentError: ArgumentError
    

    所以它显然在开发环境中调用了这个方法,因为它引发了争论错误。

    在我的测试中再次使用它,并且它仍然说该方法没有被调用...我正在使用下面的代码:

    Age.should_receive(:is_male_alive?).with(an_instance_of(Fixnum)).at_least(:once) { |age| age < 75 }
    

    我也试过这个

    Age.should_receive(:is_male_alive?).with(an_instance_of(Fixnum)).at_least(:once) { raise ArgumentError }
    

    有什么想法吗?

1 个答案:

答案 0 :(得分:7)

您可以使用块。请参阅rspec的消息期望文档中的任意处理:http://rubydoc.info/gems/rspec-mocks/frames

Age.should_receive(:is_male_alive?).with(an_instance_of(Fixnum)).at_least(:once) { |age| age < 75 }
Age.should_receive(:is_female_alive?).with(an_instance_of(Fixnum)).at_least(:once) { |age| age < 80 }