Last active
September 26, 2016 07:21
-
-
Save chikamichi/74f865959ee2471c02a6021a45d0de47 to your computer and use it in GitHub Desktop.
Test: double example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Model | |
# Let's say Elasticsearch needs a JSON representation of the model in order | |
# to index it. We delegate to a specialized class to generate that JSON: | |
def as_indexed_json | |
ModelSerializer.new(self).as_json | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
describe Model do | |
describe '#as_indexed_json' do | |
let(:model) { Model.new } | |
let(:serialization) { double } | |
let(:result) { double } | |
before do | |
expect(ModelSerializer).to receive(:new) | |
.with(model) | |
.and_return(serialization) | |
allow(serialization).to receive(:as_json) | |
.and_return(result) | |
end | |
it 'delegates and returns the result from a serializer' do | |
expect(model.as_indexed_json).to eq result | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Using RSpec syntax. | |
describe Model do | |
# In Model#as_indexed_json, we rely on a ModelSerializer class, which is an external | |
# dependency. For we are solely focused on testing Model, we'd like to avoid | |
# leveraging that dependency. We can abstract it away using double objects. | |
# | |
# The only thing we are interested in is whether the right messages are being | |
# sent to and received by the right objects. If we trump an actual object, such | |
# as ModelSerializer, with a double (fake-object), then we must take care of | |
# letting that double receive and respond to the expected messages. | |
# | |
# We can do so by actually setting up expectations (tests) that the messages will | |
# be sent, received and responded to the right way. | |
describe '#as_indexed_json' do | |
let(:model) { Model.new } | |
# Step 1: use a double for each and every object that is an external dependency | |
# (eg. serialization) or is provided by one (eg. result). | |
let(:serialization) { double } | |
let(:result) { double } | |
before do | |
# Step 2: set your expectations when it comes to messages. | |
# We expect a ModelSerializer to be created. When that happens, let's return | |
# our double instead of the actual instance. We make an assertion out of this | |
# expectation, with a precise usage of RSpec's expect method and DSL. | |
expect(ModelSerializer).to receive(:new) | |
.with(campaign) | |
.and_return(serialization) | |
# We expect the serialization to be casted to JSON. When that happens, let's | |
# return another double instead of the actual hash. The expectation is "weak", | |
# that is, we simply stub the result and don't make an assertion out of the | |
# method being called — but the actual test below will assert the result is | |
# computed and returned. | |
allow(serialization).to receive(:as_json) | |
.and_return(result) | |
end | |
it 'delegates and returns the result from a serializer' do | |
# Step 3: call the targeted method. | |
# On top of the built-in assertion about ModelSerializer#new, we make sure of | |
# checking the return form the Model#as_indexed_json, which should be our double. | |
expect(model.as_indexed_json).to eq result | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Usually, in the
before
block, I only useallow
to setup my doubles. Then, in the test I useexpect
to verify that my doubles behave as required. Sometimes I would not even expect anything from the double if I'm using it as a stub (see http://martinfowler.com/articles/mocksArentStubs.html for more explanations).I would write your example as: