【问题标题】:How to test a method call in a constructor with rspec如何使用 rspec 在构造函数中测试方法调用
【发布时间】:2011-03-11 08:54:25
【问题描述】:

我有一个这样的构造函数:

class Foo
  def initialize(options)
    @options = options
    initialize_some_other_stuff
  end
end

如果实例化一个新的 Foo 对象,想要测试对initialize_some_other_stuff 的调用。

我发现了这个问题rspec: How to stub an instance method called by constructor?,但调用Foo.any_instance(:initialize_some_other_stuff) 的建议解决方案在我的 rspec 版本 (2.5.0) 中不起作用。

谁能帮我测试这个构造函数调用?

【问题讨论】:

    标签: ruby constructor mocking rspec


    【解决方案1】:

    在您的规范中,您可以拥有以下内容:

    class Foo
      attr_reader :initializer_called
      def initialize_some_other_stuff
        @initializer_called = true
      end
    end
    
    foo = Foo.new
    foo.initializer_called.should == true
    

    如果构造函数调用initiaize_some_other_stuff方法,foo.initializer_called应该为真。

    【讨论】:

    • 嗨 gnab,谢谢你的回答。问题是,我不想调用 initialize_some_other_stuff 方法,我想模​​拟它。
    • 我明白了。我发布的代码有效地将initialize_some_other_stuff 替换为虚拟(模拟),并添加了一些功能来确定它是否已被调用,这是必需的,因为我们无法为此应用任何侦听器,因为调用发生在构造函数中。你原来的initialize_some_other_stuff 永远不会被调用。
    【解决方案2】:

    给你:

    stub_model(Foo).should_receive(:some_method_call).with(optional_argument)

    【讨论】:

      【解决方案3】:

      因为initialize_some_other_stuff 方法是类私有的,所以你不应该关心它是否执行。也就是说,如果该方法执行一些您不希望测试等待的昂贵操作,那么模拟该操作是完全可以的。

      所以,如果 Foo 看起来像这样:

      class Foo
        attr_reader :options, :other_stuff
      
        def initialize(options)
          @options = options
          initialize_some_other_stuff
        end
      
        def initialize_some_other_stuff
          @other_stuff = Bar.new.long_running_operation
        end
      end
      

      然后您可以像这样模拟对Bar#long_running_operation 的调用:

      describe Foo do
        subject(:foo) { described_class.new(options) }
      
        let(:options) { 'options' }
        let(:bar) { instance_double(Bar, long_running_operation: 42) }
      
        before do
          allow(Bar).to receive(:new).and_return(bar)
      
          foo
        end
      
        it 'initializes options' do
          expect(foo.options).to eq(options)
        end
      
        it 'initializes other stuff' do
          expect(foo.other_stuff).to eq(bar.long_running_operation)
        end
      end
      

      现在,您正在测试作业。但是,您不必等待昂贵的操作完成。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-09-23
        • 2014-02-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多