Mock with rspec
RSpec uses its own mocking framework by default. You can also configure it
explicitly if you wish.Scenarios
- Passing message expectation
- Failing message expectation
- Failing message expectation in pending example (remains pending)
- Passing message expectation in pending example (fails)
- Accessing `RSpec.configuration.mock_framework.framework_name`
- Doubles may be used in generated descriptions
Passing message expectationGivena file named “example_spec.rb” with:
RSpec.configure do |config|
config.mock_with :rspec
end
RSpec.describe "mocking with RSpec" do
it "passes when it should" do
receiver = double('receiver')
expect(receiver).to receive(:message)
receiver.message
end
end
WhenI run rspec example_spec.rb
Thenthe examples should all passFailing message expectationGivena file named “example_spec.rb” with:
RSpec.configure do |config|
config.mock_with :rspec
end
RSpec.describe "mocking with RSpec" do
it "fails when it should" do
receiver = double('receiver')
expect(receiver).to receive(:message)
end
end
WhenI run rspec example_spec.rb
Thenthe output should contain “1 example, 1 failure”Failing message expectation in pending example (remains pending)Givena file named “example_spec.rb” with:
RSpec.configure do |config|
config.mock_with :rspec
end
RSpec.describe "failed message expectation in a pending example" do
it "is listed as pending" do
pending
receiver = double('receiver')
expect(receiver).to receive(:message)
end
end
WhenI run rspec example_spec.rb
Thenthe output should contain “1 example, 0 failures, 1 pending”Andthe exit status should be 0Passing message expectation in pending example (fails)Givena file named “example_spec.rb” with:
RSpec.configure do |config|
config.mock_with :rspec
end
RSpec.describe "passing message expectation in a pending example" do
it "fails with FIXED" do
pending
receiver = double('receiver')
expect(receiver).to receive(:message)
receiver.message
end
end
WhenI run rspec example_spec.rb
Thenthe output should contain “FIXED”Thenthe output should contain “1 example, 1 failure”Andthe exit status should be 1Accessing `RSpec.configuration.mock_framework.framework_name`Givena file named “example_spec.rb” with:
RSpec.configure do |config|
config.mock_with :rspec
end
RSpec.describe "RSpec.configuration.mock_framework.framework_name" do
it "returns :rspec" do
expect(RSpec.configuration.mock_framework.framework_name).to eq(:rspec)
end
end
WhenI run rspec example_spec.rb
Thenthe examples should all passDoubles may be used in generated descriptionsGivena file named “example_spec.rb” with:
RSpec.configure do |config|
config.mock_with :rspec
end
RSpec.describe "Testing" do
# Examples with no descriptions will default to RSpec-generated descriptions
it do
foo = double("Test")
expect(foo).to be foo
end
end
WhenI run rspec example_spec.rb
Thenthe examples should all pass
Mock with mocha
Configure RSpec to use mocha as shown in the scenarios below.Scenarios
- Passing message expectation
- Failing message expectation
- Failing message expectation in pending example (remains pending)
- Passing message expectation in pending example (fails)
- Accessing `RSpec.configuration.mock_framework.framework_name`
Passing message expectationGivena file named “example_spec.rb” with:
RSpec.configure do |config|
config.mock_with :mocha
end
RSpec.describe "mocking with RSpec" do
it "passes when it should" do
receiver = mock('receiver')
receiver.expects(:message).once
receiver.message
end
end
WhenI run rspec example_spec.rb
Thenthe examples should all passFailing message expectationGivena file named “example_spec.rb” with:
RSpec.configure do |config|
config.mock_with :mocha
end
RSpec.describe "mocking with RSpec" do
it "fails when it should" do
receiver = mock('receiver')
receiver.expects(:message).once
end
end
WhenI run rspec example_spec.rb
Thenthe output should contain “1 example, 1 failure”Failing message expectation in pending example (remains pending)Givena file named “example_spec.rb” with:
RSpec.configure do |config|
config.mock_with :mocha
end
RSpec.describe "failed message expectation in a pending example" do
it "is listed as pending" do
pending
receiver = mock('receiver')
receiver.expects(:message).once
end
end
WhenI run rspec example_spec.rb
Thenthe output should contain “1 example, 0 failures, 1 pending”Andthe exit status should be 0Passing message expectation in pending example (fails)Givena file named “example_spec.rb” with:
RSpec.configure do |config|
config.mock_with :mocha
end
RSpec.describe "passing message expectation in a pending example" do
it "fails with FIXED" do
pending
receiver = mock('receiver')
receiver.expects(:message).once
receiver.message
end
end
WhenI run rspec example_spec.rb
Thenthe output should contain “FIXED”Thenthe output should contain “1 example, 1 failure”Andthe exit status should be 1Accessing `RSpec.configuration.mock_framework.framework_name`Givena file named “example_spec.rb” with:
RSpec.configure do |config|
config.mock_with :mocha
end
RSpec.describe "RSpec.configuration.mock_framework.framework_name" do
it "returns :mocha" do
expect(RSpec.configuration.mock_framework.framework_name).to eq(:mocha)
end
end
WhenI run rspec example_spec.rb
Thenthe examples should all pass
Mock with flexmock
Configure RSpec to use flexmock as shown in the scenarios below.Scenarios
- Passing message expectation
- Failing message expectation
- Failing message expectation in pending example (remains pending)
- Passing message expectation in pending example (fails)
- Accessing `RSpec.configuration.mock_framework.framework_name`
Passing message expectationGivena file named “example_spec.rb” with:
RSpec.configure do |config|
config.mock_with :flexmock
end
RSpec.describe "mocking with Flexmock" do
it "passes when it should" do
receiver = flexmock('receiver')
receiver.should_receive(:message).once
receiver.message
end
end
WhenI run rspec example_spec.rb
Thenthe examples should all passFailing message expectationGivena file named “example_spec.rb” with:
RSpec.configure do |config|
config.mock_with :flexmock
end
RSpec.describe "mocking with Flexmock" do
it "fails when it should" do
receiver = flexmock('receiver')
receiver.should_receive(:message).once
end
end
WhenI run rspec example_spec.rb
Thenthe output should contain “1 example, 1 failure”Failing message expectation in pending example (remains pending)Givena file named “example_spec.rb” with:
RSpec.configure do |config|
config.mock_with :flexmock
end
RSpec.describe "failed message expectation in a pending example" do
it "is listed as pending" do
pending
receiver = flexmock('receiver')
receiver.should_receive(:message).once
end
end
WhenI run rspec example_spec.rb
Thenthe output should contain “1 example, 0 failures, 1 pending”Andthe exit status should be 0Passing message expectation in pending example (fails)Givena file named “example_spec.rb” with:
RSpec.configure do |config|
config.mock_with :flexmock
end
RSpec.describe "passing message expectation in a pending example" do
it "fails with FIXED" do
pending
receiver = flexmock('receiver')
receiver.should_receive(:message).once
receiver.message
end
end
WhenI run rspec example_spec.rb
Thenthe output should contain “FIXED”Thenthe output should contain “1 example, 1 failure”Andthe exit status should be 1Accessing `RSpec.configuration.mock_framework.framework_name`Givena file named “example_spec.rb” with:
RSpec.configure do |config|
config.mock_with :flexmock
end
RSpec.describe "RSpec.configuration.mock_framework.framework_name" do
it "returns :flexmock" do
expect(RSpec.configuration.mock_framework.framework_name).to eq(:flexmock)
end
end
WhenI run rspec example_spec.rb
Thenthe examples should all pass
Mock with rr
Configure RSpec to use rr as shown in the scenarios below.Scenarios
- Passing message expectation
- Failing message expectation
- Failing message expectation in pending example (remains pending)
- Passing message expectation in pending example (fails)
- Accessing `RSpec.configuration.mock_framework.framework_name`
Passing message expectationGivena file named “example_spec.rb” with:
RSpec.configure do |config|
config.mock_with :rr
end
RSpec.describe "mocking with RSpec" do
it "passes when it should" do
receiver = Object.new
mock(receiver).message
receiver.message
end
end
WhenI run rspec example_spec.rb
Thenthe examples should all passFailing message expectationGivena file named “example_spec.rb” with:
RSpec.configure do |config|
config.mock_with :rr
end
RSpec.describe "mocking with RSpec" do
it "fails when it should" do
receiver = Object.new
mock(receiver).message
end
end
WhenI run rspec example_spec.rb
Thenthe output should contain “1 example, 1 failure”Failing message expectation in pending example (remains pending)Givena file named “example_spec.rb” with:
RSpec.configure do |config|
config.mock_with :rr
end
RSpec.describe "failed message expectation in a pending example" do
it "is listed as pending" do
pending
receiver = Object.new
mock(receiver).message
end
end
WhenI run rspec example_spec.rb
Thenthe output should contain “1 example, 0 failures, 1 pending”Andthe exit status should be 0Passing message expectation in pending example (fails)Givena file named “example_spec.rb” with:
RSpec.configure do |config|
config.mock_with :rr
end
RSpec.describe "passing message expectation in a pending example" do
it "fails with FIXED" do
pending
receiver = Object.new
mock(receiver).message
receiver.message
end
end
WhenI run rspec example_spec.rb
Thenthe output should contain “FIXED”Thenthe output should contain “1 example, 1 failure”Andthe exit status should be 1Accessing `RSpec.configuration.mock_framework.framework_name`Givena file named “example_spec.rb” with:
RSpec.configure do |config|
config.mock_with :rr
end
RSpec.describe "RSpec.configuration.mock_framework.framework_name" do
it "returns :rr" do
expect(RSpec.configuration.mock_framework.framework_name).to eq(:rr)
end
end
WhenI run rspec example_spec.rb
Thenthe examples should all pass
Mock with an alternative framework
In addition to rspec, mocha, flexmock, and RR, you can choose an alternate
framework as the mocking framework. You (or the framework authors) just needs
to provide an adapter that hooks RSpec’s events into those of the framework.
A mock framework adapter must expose three methods:
setup_mocks_for_rspec
- called before each example is run
verify_mocks_for_rspec
- called after each example is run
- this is where message expectation failures should result in an error with the appropriate failure message
teardown_mocks_for_rspec
- called after
verify_mocks_for_rspec
- use this to clean up resources, restore objects to earlier state, etc
- guaranteed to run even if there are failures
- called after
ScenariosMock with alternate frameworkGivena file named “expector.rb” with:
class Expector
class << self
def expectors
@expectors ||= []
end
def clear_expectors
expectors.clear
end
def verify_expectors
expectors.each {|d| d.verify}
end
end
def initialize
self.class.expectors << self
end
def expectations
@expectations ||= []
end
def expect(message)
expectations << message.to_s
end
def verify
unless expectations.empty?
raise expectations.map {|e|
"expected #{e}, but it was never received"
}.join("\n")
end
end
private
def method_missing(name, *args, &block)
expectations.delete(name.to_s)
end
public
module RSpecAdapter
def setup_mocks_for_rspec
# no setup necessary
end
def verify_mocks_for_rspec
Expector.verify_expectors
end
def teardown_mocks_for_rspec
Expector.clear_expectors
end
end
end
Givena file named “example_spec.rb” with:
require File.expand_path("../expector", __FILE__)
RSpec.configure do |config|
config.mock_with Expector::RSpecAdapter
end
RSpec.describe Expector do
it "passes when message is received" do
expector = Expector.new
expector.expect(:foo)
expector.foo
end
it "fails when message is received" do
expector = Expector.new
expector.expect(:foo)
end
end
WhenI run rspec example_spec.rb --format doc
Thenthe exit status should be 1Andthe output should contain “2 examples, 1 failure”Andthe output should contain “fails when message is received (FAILED – 1)”