Last active
December 20, 2015 12:19
-
-
Save puyo/6130127 to your computer and use it in GitHub Desktop.
One liner expect..to..change
One liner should_receives
One liner to rule them all and in the darkness bind them
This file contains hidden or 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
module CallingIt | |
module ExampleGroupClassMethods | |
def subject(name=nil, &block) | |
# Add extra methods that allow calling the block that was passed, in the | |
# example's lexical scope. | |
if block | |
define_method(:calling_it) do | |
lambda { instance_eval(&block) } | |
end | |
alias_method(:subject_call, :calling_it) | |
end | |
# Now proceed to do the things subject normally does. | |
super() | |
end | |
def calling(method_name, &block) | |
describe(method_name) do | |
let(:__its_subject) do | |
method_chain = method_name.to_s.split('.') | |
lambda do | |
method_chain.inject(subject) do |inner_subject, attr| | |
inner_subject.send(attr) | |
end | |
end | |
end | |
def should(matcher=nil, message=nil) | |
RSpec::Expectations::PositiveExpectationHandler.handle_matcher(__its_subject, matcher, message) | |
end | |
def should_not(matcher=nil, message=nil) | |
RSpec::Expectations::NegativeExpectationHandler.handle_matcher(__its_subject, matcher, message) | |
end | |
example(&block) | |
end | |
end | |
def calling_it(desc=nil, *args, &block) | |
# Create a new example, where the subject is set to the subject block, | |
# as opposed to its return value. | |
example do | |
self.class.class_eval do | |
define_method(:subject) do | |
if defined?(@_subject_calling_it) | |
@_subject_calling_it | |
else | |
@_subject_calling_it = calling_it | |
end | |
end | |
end | |
instance_eval(&block) | |
end | |
end | |
end | |
end | |
module RSpec | |
module Core | |
class ExampleGroup | |
extend CallingIt::ExampleGroupClassMethods | |
def subject_call | |
lambda { subject } | |
end | |
end | |
end | |
end |
This file contains hidden or 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 A | |
attr_reader :counter | |
def initialize(args = {}) | |
@b = args[:b] | |
@counter = 0 | |
end | |
def query | |
1 | |
end | |
def command | |
@b.command | |
end | |
def query_command | |
@b.command | |
1 | |
end | |
def query_command_side_effect | |
@b.command | |
@counter += 1 | |
1 | |
end | |
end | |
class B | |
def command | |
end | |
end | |
# ---------------------------------------------------------------------- | |
require_relative 'calling_it' | |
require_relative 'meet_expectations_matcher' | |
describe A do | |
let(:a) { A.new(b: b) } | |
let(:b) { double('b').as_null_object } | |
describe '#query' do | |
it 'should return 1' do | |
a.query.should == 1 | |
end | |
end | |
describe '#command' do | |
it 'should call command on b' do | |
b.should_receive(:command).once | |
a.command | |
end | |
end | |
describe '#query_command' do | |
it 'should return 1' do | |
a.query_command.should == 1 | |
end | |
it 'should call command on b' do | |
b.should_receive(:command).once | |
a.query_command | |
end | |
end | |
describe '#query_command_side_effect - vanilla best practice' do | |
it 'should return 1' do | |
a.query_command_side_effect.should == 1 | |
end | |
it 'should call command on b' do | |
b.should_receive(:command).once | |
a.query_command_side_effect | |
end | |
it 'should increment counter' do | |
expect { a.query_command_side_effect }.to change(a, :counter).by(1) | |
end | |
end | |
describe '#query_command_side_effect - calling_it with custom doc strings' do | |
subject { a.query_command_side_effect } | |
it 'should return 1' do | |
subject.should == 1 | |
end | |
it 'should call b.command' do | |
subject_call.should meet_expectations { b.should_receive(:command) } | |
end | |
it 'should increment counter by 1' do | |
subject_call { should change(a, :counter).by(1) } | |
end | |
end | |
describe '#query_command_side_effect - calling_it with one liners' do | |
subject { a.query_command_side_effect } | |
it { should == 1 } | |
calling_it { should change(a, :counter).by(1) } | |
calling_it { should meet_expectations { b.should_receive(:command) } } | |
end | |
describe '#query_command_side_effect - calling_it its edition' do | |
subject { a } | |
its(:query_command_side_effect) { should == 1 } | |
calling(:query_command_side_effect) { should change(a, :counter).by(1) } | |
calling(:query_command_side_effect) { should meet_expectations { b.should_receive(:command) } } | |
end | |
describe '#query_command_side_effect - expect syntax' do | |
subject { a.query_command_side_effect } | |
it 'should return 1' do | |
expect(subject).to eq(1) | |
end | |
it 'should call b.command' do | |
expect(subject_call).to meet_expectations { b.should_receive(:command) } | |
end | |
it 'should increment counter by 1' do | |
expect(subject_call).to change(a, :counter).by(1) | |
end | |
end | |
end |
This file contains hidden or 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 MeetExpectations | |
def initialize(&block) | |
@should_receives = block | |
end | |
def matches?(subject) | |
@should_receives.call # e.g. x.should_receive(:y) | |
subject.call # execute the subject (assumed to be a Proc) | |
end | |
def description | |
'met expectations' | |
end | |
end | |
module RSpec | |
module Matchers | |
def meet_expectations(&block) | |
MeetExpectations.new(&block) | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment