Is there a way to set the value of $? in a mock in Ruby?
I am testing some scripts that interface wit开发者_如何转开发h system commands. Their logic depends on the return code of the system commands, i.e. the value of $?. So, as a simplified example, the script might say:
def foo(command)
output=`#{command}`
if $?==0
'succeeded'
else
'failed'
end
end
In order to be able to test these methods properly, I would like to be able to stub out the Kernel backquote call, and set $? to an arbitrary value, to see if I get appropriate behavior from the logic in the method after the backquote call. $? is a read-only variable, so the following doesn't work:
$? = some_number
I can do some simple stuff: for example, set $? to zero or non-zero. For instance, will set $? to either 0 or 35212 (on my system, anyway), depending on the value of $?:
def fail_or_succeed(success)
if success
`echo foo`
else
`a-non-existent-command 2>&1`
end
end
What I'd really like to be able to do is to set $? to a specific value (e.g. 3, or 122), not just zero or an arbitrary non-zero. I can't figure out a way to do this. (In case it matters, I'm testing using Test::Unit and Mocha.)
EDIT: Using Dennis Williamson's suggestion:
command = "(exit 21)"
and use if $?.exitstatus == 0
instead of if $? == 0
module Stubbed
def `(*args)
super( "mycommand that returns the error code I want" )
end
end
Include this into your object when needed?
You could launch a subprocess from the tests that would just exit with whatever code you need. This will set the $?.exitstatus
code for you, which will be available from the production code
For a production code like this:
def execute_something
`my_command --parameter`
$?.exitstatus == 0
end
You could mock the $?.exitstatus
:
it 'should return false' do
fork { exit 1 } # Change to whatever code you need
Process.wait
expect(@sut).to receive(:`).with('my_command --parameter')
expect(@sut.execute_something).to be == false
end
精彩评论