Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
The Anatomy of a mocked call - RuLu 2014
Search
Penelope Phippen
June 18, 2014
Technology
190
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
The Anatomy of a mocked call - RuLu 2014
Penelope Phippen
June 18, 2014
More Decks by Penelope Phippen
See All by Penelope Phippen
Introducing Rubyfmt
penelope_zone
0
610
How RSpec Works
penelope_zone
0
6.8k
Quick and easy browser testing using RSpec and Rails 5.1
penelope_zone
1
110
Teaching RSpec to play nice with Rails
penelope_zone
2
180
Little machines that eat strings
penelope_zone
1
130
What is processor (brighton ruby edition)
penelope_zone
0
140
What is processor?
penelope_zone
1
390
extremely defensive coding - rubyconf edition
penelope_zone
0
290
Agile, etc.
penelope_zone
2
260
Other Decks in Technology
See All in Technology
Claude Codeとのおしゃべりでセマンティックモデルの定義からダッシュボード作成まで完成させる
nic_sugiyama
0
120
就職⽀援サービスにおけるキャリアアドバイザーのシフトスケジューリング
recruitengineers
PRO
1
150
日本 Fintech 未来予測レポート 2027〜2028年(オリジナル版)
8maki
0
2.2k
入門!AWS Blocks
ysuzuki
1
140
20260619 私の日常業務での生成 AI 活用
masaruogura
1
220
あなたの知らないPDFのアクセシビリティ
lycorptech_jp
PRO
0
200
【NRUG vol.18】KubernetesにおけるNew Relicデータ取得量削減の考え方
nrug_member
0
150
Oracle AI Database@Google Cloud:サービス概要のご紹介
oracle4engineer
PRO
6
1.5k
Agent Skills設計で柔軟性と硬さのバランスが難しい話
nassy20
0
130
AI駆動開発を通して感じた、 AI時代のデザイナーの役割変化
whisaiyo
3
2.2k
非エンジニアがClaudeと挑んだ「1ヶ月間プロダクト30本ノック」
askokc
0
590
人材育成分科会.pdf
_awache
4
270
Featured
See All Featured
How to optimise 3,500 product descriptions for ecommerce in one day using ChatGPT
katarinadahlin
PRO
1
3.6k
SEO Brein meetup: CTRL+C is not how to scale international SEO
lindahogenes
1
2.7k
What's in a price? How to price your products and services
michaelherold
247
13k
From π to Pie charts
rasagy
0
210
Speed Design
sergeychernyshev
33
1.8k
How To Speak Unicorn (iThemes Webinar)
marktimemedia
1
490
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
287
14k
The Curious Case for Waylosing
cassininazir
1
390
Into the Great Unknown - MozCon
thekraken
41
2.6k
Primal Persuasion: How to Engage the Brain for Learning That Lasts
tmiket
0
370
A Tale of Four Properties
chriscoyier
163
24k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
16
2k
Transcript
The Anatomy of a mocked call
!/samphippen
Hello everyone :)
Why is testing?
x`
None
Tests force behaviour
Without tests Anything could happen
Unit Testing makes me happy :)
Stubbing and mocking
Stubbing
Fake response to a method
allow(x).to( receive(:foo).and_return(3) )
x.foo will return 3
Mocking
Testing methods get called
expect(x).to receive(:foo)
Test fails if x does not receive foo
expect(x).to receive(:foo).with(3)
expect(x).to( receive(:foo) .with(3) .exactly(4).times )
How does it work?
Stubs
it “does something” do allow(foo).to receive(:bar) expect(foo.bar).to eq(nil) end
it “does something” do allow(foo).to receive(:bar) expect(foo.bar).to eq(nil) end
allow is syntax sugar for AllowanceTarget.new
Allowance Target
Allowance Target TargetBase
AllowanceTarget calls #delegate_to with :setup_allowance on TargetBase
Allowance Target TargetBase
TargetBase defines #to on AllowanceTarget
Defined #to calls :setup_allowance on matchers passed to #to
Allowance Target TargetBase
it “does something” do allow(foo).to receive(:bar) expect(foo.bar).to eq(nil) end
Things passed to #to are called “matchers”
Receive is a commonly used mocking/stubbing matcher
AllowanceTarget#to calls setup_allowance on the passed matcher
Allowance Target TargetBase Allowance Target TargetBase Receive
Receive#setup_allowance creates a Mock Proxy for object
Receive#setup_allowance calls #add_stub on the Mock Proxy
Allowance Target TargetBase Receive Proxy
Proxy objects manage all mocks/stubs for an object
it “does something” do allow(foo).to receive(:bar) allow(foo).to receive(:baz) expect(foo.bar).to eq(nil)
end
Proxy#add_stub creates a MethodDouble for the stubbed method
Allowance Target TargetBase Proxy Receive Method Double
MethodDouble saves the original implementation
MethodDouble creates stub implementation
it “does something” do allow(foo).to receive(:bar) expect(foo.bar).to eq(nil) end
it “does something” do allow(foo).to receive(:bar) expect(foo.bar).to eq(nil) end
foo.bar is the stubbed implementation
Call foo.bar
Method Double Call foo.bar
Method Double Call foo.bar Proxy
Method Double Call foo.bar Proxy Invokes stub
Method Double Call foo.bar Proxy Invokes stub Return value
it “does something” do allow(foo).to receive(:bar) expect(foo.bar).to eq(nil) end
RSpec manages lifecycle of mocks
RSpec::Mocks.setup
RSpec::Mocks.setup Your test
RSpec::Mocks.setup Your test RSpec::Mocks.verify
RSpec::Mocks.teardown RSpec::Mocks.setup Your test RSpec::Mocks.verify
All of this happens in a mock space
Allowance Target TargetBase Proxy Receive Method Double
RSpec::Mocks.teardown calls #reset_all on the current Space
Space#reset_all calls #reset on each proxy
Proxy#reset calls #reset on each MethodDouble
MethodDouble#reset returns original methods to objects
RSpec::Mocks.teardown RSpec::Mocks.setup Your test RSpec::Mocks.verify
Phew
Mocks
it “does something” do expect(foo).to receive(:bar).with(3) expect(foo.bar(3)).to eq(nil) end
expect is syntax sugar for ExpectationTarget.new
Expectation Target TargetBase Proxy Receive Method Double
Calls #setup_expectation
it “does something” do expect(foo).to receive(:bar).with(3) expect(foo.bar(3)).to eq(nil) end
Receive stores details of stubbed/ mocked implementation
Expectation Target TargetBase Proxy Receive Method Double
Method Double Call foo.bar Proxy Invokes stub Return value
Proxy callback checks arguments
Proxy raises if args don’t match
it “does something” do expect(foo).to receive(:bar).with(3) expect(foo.bar(3)).to eq(nil) end
RSpec::Mocks.teardown RSpec::Mocks.setup Your test RSpec::Mocks.verify
RSpec::Mocks.verify calls Space#verify_all
Space#verify_all calls #verify on each Proxy
Proxy raises if mock not called
And that’s how it all works :)
RSpec::Mocks.teardown RSpec::Mocks.setup Your test RSpec::Mocks.verify
expect(x).to receive(:foo) allow(x).to receive(:foo)
Target TargetBase
expect(x).to receive(:foo) allow(x).to receive(:foo)
Target TargetBase
expect(x).to receive(:foo) allow(x).to receive(:foo)
Receive
Proxy Receive
Proxy Receive Method Double
Target TargetBase Proxy Receive Method Double
Method Double Call foo.bar Proxy Invokes stub Return value
Target TargetBase Proxy Receive Method Double
RSpec 3.0.0 is out Please use it
tinyurl.com/ samrl2014
Let’s have some questions !/samphippen
[email protected]