我有一个类:
class Asker
def initialize
@cli = HighLine.new
end
def exit_or_continue
answer = @cli.ask "Type 'quit' to exit at any time, Press 'Enter' to continue"
exit(0) if answer == 'quit'
end
end
如何测试exit_or_continue
方法?
据我了解,您想根据用户输入来测试exit_or_continue
方法。在这种方法中,有两个重要的事情。其中之一是@cli.ask
所做的用户输入,另一个是exit
方法,如果用户输入为quit
,则辞职。
要测试这些流量,我们需要对Kernel.exit
和HighLine#ask
方法固执。首先,我们覆盖Asker
类实例中的Kernel.exit
方法。Kernel
模块包含在Object
类中,每个类都隐含在Ruby中扩展Object
类。因此,我们的Asker
类具有Kernel
的方法。
为什么我们将exit
方法存根在Asker
类的实例内,这将导致出乎意料的问题,如果我们将其固定在全球范围内(内核)。更重要的是,除非我们存根此方法RSPEC退出,并且未运行其余的测试。
其次,我们需要固执 HighLine#ask
方法,该方法等待客户端的输入。HighLine#ask
是方法,这使用引擎盖下的Kernel.gets
。通过使用此方法,我们基本上说'请返回此值,不要等待用户输入。'。换句话说,使用@cli.stub(ask: 'quit')
,这将返回quit
或您想要的任何内容,而没有提示。
所以我认为以下测试将满足您的需求。如果您遇到任何问题,请随时发表评论。
RSpec.describe Asker do
describe '#exit_or_continue' do
before do
@asker = Asker.new
@cli = @asker.instance_variable_get('@cli')
@asker.stub(exit: true) # We override Kernel.exit method inside asker instance
end
context 'when user input is quit' do
it 'returns true' do
@cli.stub(ask: 'quit') # We stub HighLine#ask method to return quit on behalf of the user.
expect(@sker.exit_or_continue).to be(true)
end
end
context 'when user is input is NOT quit' do
it 'returns nil' do
@cli.stub(ask: 'invalid response') # We stub HighLine#ask method to return invalid response on behalf of the user.
expect(@sker.exit_or_continue).to be_nil
end
end
end
end