【问题标题】:Writing RSpec to isolate and test specific methods in class编写 RSpec 以隔离和测试类中的特定方法
【发布时间】:2017-10-03 23:59:21
【问题描述】:

为使用类的 gem 编写单元测试的最佳方法是什么?我编写了一个 gem,它在初始化期间执行包括外部集成的操作。在编写测试时,我不想初始化所有内容,我只想测试某些功能。

比如我有lib/foomon.rb:

class FooMon
  def initialize
    @log = Logger.new("app.log","daily")
    pollingClient = SomePoller.new(remote_service_url)
    pollingClient.poll do |response|
       processResponse(response)
    end
  end

  private 

  def processResponse(res)
    {:response => res.body}
  end
end

现在我想测试processResponse 函数。我采用的方法是删除private 修饰符,然后将代码从initialize 移动到新的setup 方法。然后应用程序的主要入口点调用 setup,但我的测试没有(它们只有 before 中的 @foomon = FooMon.new)。然后规范可以测试@foomon.processResponse

这是最好的方法吗?

【问题讨论】:

    标签: ruby rspec rubygems


    【解决方案1】:

    当我过去这样做时,我倾向于使用RSpec Mocks (doubles)。我认为,在您的特定情况下,存根 #body 的 double 可以解决问题。

    RSpec.describe FooMon do
      before do
        @foomon = FooMon.new
      end
    
      it "should process the response" do
        response = instance_double("Response")
        expect(response).to receive(:body).once.and_return("I ain't got no body ...")
    
        expect {response_body = @foomon.send(:process_response, response)}.not_to raise_error
        expect response_body == "I ain't got no body ..."
      end
    end
    

    免责声明:写在浏览器中,来自老化的记忆。可能需要调试。

    这是我能找到的最好的real-life, working example。希望这有助于提供一些颜色。

    【讨论】:

      【解决方案2】:

      规范应该只测试公共方法,如果你去掉这个类的私有修饰符实际上processResponce可以测试,否则那里没有什么可测试的。

      关于类的外部集成,在单元测试方法中,您应该只测试从类本身返回的内容。

      在这种情况下,您应该只测试从processResponce 返回的内容,其他类(如LoggerSomePoller)生成的所有逻辑都应该在其他规范上测试,而不是在这个规范中测试。

      在这种情况下,我建议更改初始化程序中的逻辑并将其移至单独的公共方法。这样该方法就可以负责将消息发送给客户端,并且更容易测试。

      您可以使用double 模拟这些类的行为。像这样:

      let(:poller) { double(:poller)
      let(:responce) { double(:responce, body: "message") }
      
      before do
        allow(poller).to receive(:poll).and_yield(responce)
        allow(SomePoller).to response(:new) { poller }
      end
      
      it 'send a message to the client' do
        expect(response).to receive(:body).once
        subject.send_client
      end
      

      这样,您只能测试类职责,并且注释会使您的测试过于复杂。

      参考资料:

      https://www.relishapp.com/rspec/rspec-mocks/v/3-6/docs/ https://relishapp.com/rspec/rspec-mocks/docs/configuring-responses/yielding#yield-an-argument

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-11-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-11
        相关资源
        最近更新 更多