【问题标题】:test ruby class method calls method in another gem测试 ruby​​ 类方法调用另一个 gem 中的方法
【发布时间】:2016-12-15 11:31:24
【问题描述】:

所以我有一个 ruby​​ 类,它可以导入并使用一个 ruby​​ gem。 gem 是自己测试的,但我想编写一个测试来确保我的类方法调用 gem 上的正确方法。

我不确定这将如何工作。

这是我的类方法:

  def article_body
    renderer = ArticleBodyRenderer.new
    renderer.to_html(data.fetch(:body))
  end

我希望我的测试检查此方法是否调用:renderer.to_html()

我将如何在 ruby​​ 中做到这一点。我正在使用 rspec 单元测试。

【问题讨论】:

    标签: ruby rspec rubygems


    【解决方案1】:

    您应该将renderer 实例提取到它自己的方法中:

    def renderer
      @renderer ||= ArticleBodyRenderer.new
    end
    
    def article_body
      renderer.to_html(data.fetch(:body))
    end
    

    这使您可以更轻松地模拟它,例如使用instance double

    renderer_double = instance_double('ArticleBodyRenderer')
    allow(your_instance).to receive(:renderer).and_return(renderer_double)
    
    expect(renderer_double).to receive(:to_hml).with(...)
    your_instance.article_body
    

    或通过spy

    renderer_spy = spy('ArticleBodyRenderer')
    allow(your_instance).to receive(:renderer).and_return(renderer_spy)
    
    your_instance.article_body
    expect(renderer_spy).to have_received(:to_hml).with(...)
    

    【讨论】:

    • 太棒了,谢谢!使用 instance_double 的例子很棒
    【解决方案2】:

    为确保方法中的renderer 初始化被存根,您需要使用"Any instance of" stub。所以:

    let(:formatted_text) { '<foo>bar</foo>' }
    
    it 'calls the to_html on rendered' do
      allow_any_instance_of(ArticleBodyRenderer).to receive(:to_html).and_return(formatted_text)
      expect(subject.article_body).to eq(formatted_text)
    end
    

    【讨论】:

    • 谢谢,测试通过了!
    【解决方案3】:

    应该是这样的:

    let(:renderer) { ArticleBodyRenderer.new }
    
    it 'calls the to_html on rendered' do
      expect(renderer).to receive(:to_html)
      subject.article_body
    end
    

    逻辑如下:首先你说你希望某个对象接收一些消息(在这个对象上调用方法),然后你触发了一些东西,它实际上应该对预期的对象执行预期的方法调用。

    【讨论】:

    • 大坝真的那么容易吗?我现在试试这个。感谢您的评论。
    • 我能问一下这条线是subject.article_body
    • @chinds 所以逻辑如下:首先你说你希望某个对象接收一些消息(在这个对象上调用方法),然后你触发一些东西,这实际上应该执行预期对预期对象的方法调用。
    • 好的,有道理。因此,以您的示例为例,该测试失败了。它说它不能在这一行subject.article_body 上对键body 进行罚款,我的猜测是因为它认为这是一个对象上的方法,而实际上它是一个名为Article的更大类的一部分@
    • let 语句中的renderer 实例与article_body 中创建的实例不同。我认为您需要使用“任何实例”存根:relishapp.com/rspec/rspec-mocks/docs/working-with-legacy-code/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多