2017-05-05 58 views
0

对于使用类的gem编写单元测试的最佳方法是什么?我写了一个gem,它在初始化过程中执行包含外部集成的事情。在编写测试时,我不想初始化所有的东西,我只想测试某些函数。编写RSpec来隔离和测试类中的特定方法

例如,我有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方法。该应用程序的主要入口点然后调用设置,但我的测试不(他们只有@foomon = FooMon.newbefore)。该规范则可以测试@foomon.processResponse

这是最好的方法?

回答

1

当我已经在过去做到了这一点,我倾向于使用RSpec Mocks (doubles)。在你的具体情况下,我认为,存在#body的双重存在是可行的。

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我可以把我的手。希望这有助于提供一些颜色。

1

的规格应该只测试公有方法,如果你删除这个类其实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