No commit activity in last 3 years
No release in over 3 years
Simple cross process stubbing
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

>= 0.0.0
>= 0.4.0

Runtime

>= 1.2.5
>= 0.4.0
 Project Readme

CROSS-STUB makes cross process stubbing possible !!¶ ↑

IMPORTANT: CrossStub is no longer maintained, use it at your own risk, & expect no bug fixes.¶ ↑

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 another process, 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 using selenium, culerity, steam, blah, blah driver? 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.

$ gem install cross-stub

Setting Up¶ ↑

1. Rails-3.*¶ ↑

$ rails g cucumber:install
$ rails g cross_stub

2. Rails-2.*¶ ↑

$ ./script/generate cucumber
$ ./script/generate cross_stub

3. Others (back to basics)¶ ↑

# In the test setup method:
CrossStub.setup :file => <CACHE_FILE>

# 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>

For a full list of available cache stores, scroll down to take a look at the ‘Cache Stores’ section.

Using It¶ ↑

Cross-stubbing is simple:

1. Simple returning of nil or non-nil value:¶ ↑

1.1. Class method:¶ ↑

class Someone
  def self.say
    'hello'
  end
end

Someone.xstub(:say)
Someone.say # yields: nil

Someone.xstub(:say => 'HELLO')
Someone.say # yields: 'HELLO'

1.2. Instance method:¶ ↑

Someone.xstub(:say, :instance => true)
Someone.new.say # yields: nil

Someone.xstub({:say => 'HELLO'}, :instance => true)
Someone.new.say # yields: 'HELLO'

2. If a stubbed method requires argument, pass xstub a proc:¶ ↑

2.1. Class method:¶ ↑

Someone.xstub do
  def say(something)
    'saying "%s"' % something
  end
end

Someone.say('HELLO') # yields: 'saying "HELLO"'

2.2. Instance method:¶ ↑

Someone.xstub(:instance => true) do
  def say(something)
    'saying "%s"' % something
  end
end

Someone.new.say('HELLO') # yields: 'saying "HELLO"'

3. Something more complicated:¶ ↑

something = 'hello'
Someone.xstub do
  def say
    'saying "%s"' % something
  end
end

Someone.say # failure !!

The above fails as a result of undefined variable/method ‘something’, to workaround we can have:

Someone.xstub(:something => 'HELLO') do
  def say
    'saying "%s"' % something
  end
end

Someone.say # yields: 'saying "HELLO"'

Cache Stores¶ ↑

Cache stores are needed to allow stubs to be made available for different processes. The following describes all cache stores available:

1. File¶ ↑

# Setting up (current process)
CrossStub.setup :file => '<CACHE_FILE>'

# Refreshing (other process)
CrossStub.refresh :file => '<CACHE_FILE>'

2. Memcache (requires memcache-client gem)¶ ↑

# Setting up (current process)
CrossStub.setup :memcache => 'localhost:11211/<CACHE_ID>'

# Refreshing (other process)
CrossStub.refresh :memcache => 'localhost:11211/<CACHE_ID>'

3. Redis (requires redis gem)¶ ↑

# Setting up (current process)
CrossStub.setup :redis => 'localhost:6379/<CACHE_ID>'

# Refreshing (other process)
CrossStub.refresh :redis => 'localhost:6379/<CACHE_ID>'

Adding new store is super easy (w.r.t testing & actual implementation), let me know if u need more :]

Caveats¶ ↑

  1. CrossStub uses ruby’s Marshal class to dump & load the stubs, thus it has the

same limitations as Marshal (pls note abt a 1.9.1 specific marshal bug at redmine.ruby-lang.org/issues/show/3729)

  1. Under the hood, CrossStub uses Sourcify (github.com/ngty/sourcify) for

extracting the methods defined within the proc, u may wish to read Sourcify’s gotchas to avoid unnecessary headaches.

TODO(s)¶ ↑

  1. Is there any better serialization strategy instead of the current Marshal load/dump?

Contacts¶ ↑

Written since 2009 by:

  1. NgTzeYang, contact ngty77[at]gmailcom or github.com/ngty

  2. WongLiangZan, contact liangzan[at]gmailcom or github.com/liangzan

Released under the MIT license