| ruby stuff: Not A Mock | Time Travel | mac stuff: SimpleSynth | MIDI Patchbay | PYMIDI | NHCollections |
A cleaner and DRYer alternative to mocking and stubbing with RSpec.
Not A Mock extends RSpec so you can stub out methods (or entire objects), then make assertions about the calls to those methods after the fact.
I have a Rails app that has a Message model that stores and sends SMS messages. I'd like to test it, but I don't want it delivering the test messages.
The Not A Mock way:
describe Message, "deliver method" do before do # Replace the send_message method on our singleton SMSGateway # with a version that does nothing and returns true. SMSGateway.instance.stub_method(:send_message => true) @message = messages(:sample_message) @message.deliver end it "should pass the message to the gateway" do # Make sure the send_message method was called with the right arguments. SMSGateway.instance.should have_received(:send_message).with(@message.recipient, @message.body) end it "should mark the message as sent" do @message.status.should == "sent" end end
The old-fashioned way, using RSpec's standard stubbing and mocking:
describe Message, "deliver method" do before do @message = messages(:sample_message) end it "should pass the message to the gateway" do # Create a mock object to replace the gateway. @gateway = mock("SMSGateway") # Assert in advance what methods should be called on the mock object. @gateway.should_receive(:send_message).with(@message.recipient, @message.body) # Make the gateway class return the mock object as the singleton. SMSGateway.stub!(:instance).and_return(@gateway) @message.deliver end it "should mark the message as sent" do # Replace the send_message method on our singleton SMSGateway # with a version that does nothing and returns true. SMSGateway.instance.stub!(:send_message).and_return(true) @message.deliver @message.status.should == "sent" end end
See the RDoc documentation for more details.
(The following describes using NotAMock with Rails. It should also work outside of Rails, but it's untested.)
First, install the rspec and rspec_on_rails plugins:
ruby script/plugin install http://rspec.rubyforge.org/svn/tags/CURRENT/rspec ruby script/plugin install http://rspec.rubyforge.org/svn/tags/CURRENT/rspec_on_rails ruby script/generate rspec
(See the RSpec docs for more details.)
Second, install the not_a_mock plugin:
ruby script/plugin install git://github.com/notahat/not_a_mock.git
Finally, add the following to your project‘s spec/spec_helper.rb:
config.mock_with NotAMock::RspecMockFrameworkAdapter