CROSS-STUB makes cross process stubbing possible !!
Introduction
Existing mocking/stubbing frameworks support only stubbing in the current process. This is OK most of the time. However, when running cucumber integration test suite in non-webrat mode, these in-process stubbing frameworks simply doesn’t help. Eg. I want Time.now to always return a timing that should be a Sunday, how do I do that when running cucumber in selenium, culerity, steam, blah, blah mode? It doesn’t seem straight-forward me.
(Let’s not argue whether stubbing should be encouraged. It is an itch, the poor itch needs to be scratched.)
Getting Started
It’s hosted on gemcutter.org.
$ sudo gem install cross-stub
Setting Up
#1. If you are using rails, you are in luck:
$ ./script/generate cucumber
$ ./script/generate cross_stub
#2. Even if you are using something else, no worries:
# In the test setup method:
CrossStub.setup :file => <CACHE_FILE_PATH>
# In the test teardown method:
CrossStub.clear
# Find an entry point in your target application, eg. in a server, the
# point where all request handling starts:
CrossStub.refresh :file => <CACHE_FILE_PATH>
Using It
Using cross-stub is simple:
#1. Simple returning of nil or non-nil value:
class Someone
def self.laugh
'HaHa'
end
end
Someone.xstub(:laugh)
Someone.laugh # yields: nil
Someone.xstub(:laugh, 'HoHo')
Someone.laugh # yields: 'HoHo'
#2. If a stubbed method requires argument, pass :xstub a proc:
Someone.xstub do
def loves(other)
"I love #{other}"
end
end
Someone.loves('you') # yields: 'I love you'
#3. Something more complicated:
something = 'hello'
Someone.xstub do
def do_action(who, action)
%\#{who} #{action} #{something}\
end
end
Someone.do_action('i', 'say') # failure !!
The above fails as a result of undefined variable/method ‘something’, to workaround we can have:
Someone.xstub(:something => 'hello') do
def do_action(who, action)
%\#{who} #{action} #{something}\
end
end
Someone.do_action('i', 'say') # yields: 'i say hello'
Caveats
#1. Cross-stub uses ruby’s Marshal class to dump & load the stubs, thus it has the same limitations as Marshal
#2. Cross-stub only supports stubbing of class methods, since it makes no sense to do cross process stubbing of instances
TODO(s)
#1. We can possibly use Hijack (github.com/ileitch/hijack) within the current test process to trigger refreshing of stubs in the other process, thus using cross-stub no longer requires changing of any existing application code to insert CrossStub.refresh(…). This has in fact been our original intended strategy, however, we have not been able to do so as Hijack currently hangs on starting up on our development machines.
Contacts
Written 2009 by:
#1. NgTzeYang, contact ngty77gmail.com or github.com/ngty
#2. WongLiangZan, contact liangzangmail.com or github.com/liangzan
Released under the MIT license