模拟一个类的本地方法

时间:2013-07-17 12:34:53

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

我正在尝试在Rpec中编写一个类似于

的类的测试用例
class ABC
   def method_1( arg )
       #does something and return a value based on arg
   end

   def initialize
       @service = method_1( arg )
   end

   def getSomething_1
       return @service.get_seomthing_1
   end

   def getSomething_2
       return @service.get_seomthing_2
   end
end

现在我想用一个模拟对象启动@service实例变量,这样我就可以使用那个模拟对象来返回值,我可以用来验证我的单元测试。

我尝试做类似

的事情
describe ABC do
    before(:each) do
       myObject = double()
       myObject.stub(:get_something_1).and_return("SomeValue")
       ABC.any_instance.stub(:method_1).and_return(myObject)
    end

   it "Checks the correctness of getSomething_1 method of class ABC" do
       @abc = ABC.new
       @abc.getSomething_1.should eql("SomeValue")
   end
end

当我尝试运行测试时没有@service没有使用我想要的对象进行初始化。 看起来像method_1并没有被定义的行为嘲笑。 有人可以帮助我如何使用我的模拟对象分配@service。

2 个答案:

答案 0 :(得分:0)

你真的很接近,但看起来你在ABC的一个实例上错误地存根:method_1。您需要执行以下操作:

before(:each) do
  myObject = double(get_something_1: "SomeValue")
  ABC.any_instance().should_receive(:method_1).and_return(myObject)
end

答案 1 :(得分:0)

你遇到的问题是你正在使用:method_1,它允许你控制返回的内容,但是在短路其行为时 。不幸的是,method_1返回的内容是无关紧要的,它是所做的 - 分配@service - 这很有趣。

如果没有看到类的实际界面和设计,我无法建议对该分数进行改进,但您至少可以通过将引用替换为实例变量来使您的期望正常工作(即。@service.some_method )使用attr_reader:

class ABC
  attr_reader :service

  # ...

  def getSomething_1
    return service.get_seomthing_1
  end
end

然后在你的规范中:

describe ABC
  # ..

  before do
    ABC.any_instance(:service).and_return(myObject)
    # ...
  end

  it "Checks the correctness of getSomething_1 method of class ABC" do
    @abc = ABC.new("xyz")
    @abc.getSomething_1.should eql("SomeValue")
  end
end

在这种情况下,ABC的任何实例都会在调用其属性service时返回模拟,允许getSomething_1正确引用您的模拟。