Skip to main content
Test Double company logo
Services
Services Overview
Holistic software investment consulting
Software Delivery
Accelerate quality software development
Product Management
Launch modern product orgs
Legacy Modernization
Renovate legacy software systems
DevOps
Scale infrastructure smoothly
Upgrade Rails
Update Rails versions seamlessly
Technical Recruitment
Build tech & product teams
Technical Assessments
Uncover root causes & improvements
Case Studies
Solutions
Accelerate Quality Software
Software Delivery, DevOps, & Product Delivery
Maximize Software Investments
Product Performance, Product Scaling, & Technical Assessments
Future-Proof Innovative Software
Legacy Modernization, Product Transformation, Upgrade Rails, Technical Recruitment
About
About
What's a test double?
Approach
Meeting you where you are
Founder's Story
The origin of our mission
Culture
Culture & Careers
Double Agents decoded
Great Causes
Great code for great causes
EDI
Equity, diversity & inclusion
Insights
All Insights
Hot takes and tips for all things software
Leadership
Bold opinions and insights for tech leaders
Developer
Essential coding tutorials and tools
Product Manager
Practical advice for real-world challenges
Say Hello
Test Double logo
Menu
Services
BackGrid of dots icon
Services Overview
Holistic software investment consulting
Software Delivery
Accelerate quality software development
Product Management
Launch modern product orgs
Legacy Modernization
Renovate legacy software systems
Cycle icon
DevOps
Scale infrastructure smoothly
Upgrade Rails
Update Rails versions seamlessly
Technical Recruitment
Build tech & product teams
Technical Assessments
Uncover root causes & improvements
Case Studies
Solutions
Solutions
Accelerate Quality Software
Software Delivery, DevOps, & Product Delivery
Maximize Software Investments
Product Performance, Product Scaling, & Technical Assessments
Future-Proof Innovative Software
Legacy Modernization, Product Transformation, Upgrade Rails, Technical Recruitment
About
About
About
What's a test double?
Approach
Meeting you where you are
Founder's Story
The origin of our mission
Culture
Culture
Culture & Careers
Double Agents decoded
Great Causes
Great code for great causes
EDI
Equity, diversity & inclusion
Insights
Insights
All Insights
Hot takes and tips for all things software
Leadership
Bold opinions and insights for tech leaders
Developer
Essential coding tutorials and tools
Product Manager
Practical advice for real-world challenges
Say hello
Testing

Please mock me

Looking for a better way to mock things in Ruby? Here's a quick rundown of what it's like to use our new Mocktail library in a RailsConf 2022 lightning talk presented by Justin Searls.
Justin Searls
|
May 18, 2022
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

This lightning talk was recorded at RailsConf 2022 in Portland, Oregon. It shows off our new mocking library for Ruby, Mocktail.

It’s a bit of a whirlwind, so don’t feel bad if anything goes over your head! Please feel free to take your time perusing the library’s expansive README.

If you’re looking for another talk on this topic, consider watching the companion talk, Please don’t mock me. It’s a much longer talk, and so it takes the time needed to discuss some of the patterns and pitfalls to keep in mind when using test doubles in your tests.


[00:00] - Okay, so the title of this presentation is
[00:01] "Please Mock Me."
[00:02] So hello everyone, Portland.
[00:04] Lovely weather today.
[00:05] A year and a half ago,
[00:06] I moved to Florida.
[00:08] So today, you know, the weather's really
[00:09] selling me on Orlando.
[00:11] I'm talking here about test doubles,
[00:13] not our company Test Double,
[00:15] but rather the concept of test double.
[00:17] It's just a highbrow way to say a mock object.
[00:20] So we're gonna talk about that today.
[00:21] Now Rubyists have lots of options for mocking.
[00:24] You have tools like Mocha, rspec-mocks,
[00:26] rr, flexmock,
[00:27] minitest has a built in mock thing.
[00:30] There's probably others, but the WiFi's not working.
[00:33] I've got a secret,
[00:34] which is I don't like any of them.
[00:37] And so, you know, my approach to open source
[00:39] is actually very unlike what Eileen presented today,
[00:41] and we're gonna talk about that through this pop quiz.
[00:43] So get ready.
[00:45] Here's the question:
[00:46] what should you do when you don't like an open source thing?
[00:48] And you have two options:
[00:49] Option A, help improve the thing,
[00:51] or Option B, create a brand new thing.
[00:53] - [Audience] B!
[00:55] - Yeah, my style is I create a brand new thing, ignorantly.
[00:58] So that's how this gem happened
[00:59] and you can gem install mocktail.
[01:02] So let's say we have a class called "CreatesSlides"
[01:04] and it's got a method called "create",
[01:05] and you pass in a topic
[01:07] and then it it literally opens the Keynote app.
[01:08] And so this is disruptive to call from a test.
[01:12] So you might say, "Hey, I wanna fake this."
[01:14] Now we don't have time today to answer,
[01:15] "Should you fake this?"
[01:16] That's the companion talk called "Please Don't Mock Me"
[01:19] and that's a 50 minute one,
[01:20] so there's more to talk about there.
[01:22] So let's say I wanna fake this.
[01:24] And so, alright.
[01:25] So I got the class there.
[01:26] All I say is make me a Mocktail of "CreatesSlides"
[01:30] and then it returns it.
[01:31] So that's a fake thing,
[01:32] and then I can call all of the methods on it
[01:35] and call it with create("Mocking").
[01:36] It just returns nil by default.
[01:39] So you might say, "Oh, I wanna stub this,"
[01:40] and stub just means to like kind of configure a response
[01:43] for a mocked method.
[01:44] So here, I've got this DSL method "stubs"
[01:47] and I call the method just like I expect the subject
[01:49] under test to call it,
[01:50] and then I chain with "with".
[01:53] In that block there,
[01:53] I just return whatever I wanted to return.
[01:55] So, I've made the stub and I called this a demonstration.
[01:59] So it's very greppable, like the subject and the test
[02:02] both usually have the exact same indication,
[02:03] so it's really clear and not confusing.
[02:05] And then this, when the stubbing is satisfied
[02:08] and called the same way, it's gonna return that array.
[02:11] Okay, so it just looks like this.
[02:12] I call "slides.create("Mocking")",
[02:13] it returns the array.
[02:14] I call it with "Not Mocking" and it just returns nil
[02:17] 'cause the subbing wasn't satisfied.
[02:18] It's a super duper robust API.
[02:20] It can do everything that you might ever want to do,
[02:22] especially stuff you shouldn't.
[02:23] So like if I wanna ensure that a string is passed
[02:26] and I don't wanna use a type system,
[02:28] I could just write this test,
[02:29] and I say, "stubs{slides.create()}"
[02:31] and then I can take a block parameter,
[02:33] which is like a little matcher DSL,
[02:35] and I say "m.is_a(String)",
[02:37] and only when that matcher is matched,
[02:38] then return some slides.
[02:40] And so I can call it then with "Mocking", you know,
[02:43] "Literally any string",
[02:44] or like a number here and then that's not satisfied,
[02:46] so that will return nil.
[02:48] And so there's lots of built-in matchers,
[02:50] as well as a custom matcher API that you can play with.
[02:53] So the README has everything you want about stubbing.
[02:56] You know, it's good because the itty bitty scroll bar
[02:58] so it's like very long.
[02:59] (audience laughs)
[03:00] So let's say you want to verify
[03:02] that a certain thing was called.
[03:03] So I say "slides.create("Neat")".
[03:05] I call that.
[03:06] I wanna make sure it's called,
[03:07] I can just say "verify" that "slides.create"
[03:09] was called with "Neat".
[03:10] And then it just returns nil, it's passed.
[03:13] And so if I say,
[03:14] "Hey, verify that it was also called with "Cool",
[03:15] that's gonna blow up 'cause it didn't happen.
[03:17] So you got this really nice error message that says,
[03:18] "Hey, expected to be called with, you know,
[03:20] "create" with "Cool".
[03:22] It was actually called differently one time with "Neat",
[03:24] and it prints it out so you can kind of have a hope
[03:26] of figuring it out.
[03:27] Now it's a symmetrical API with stubs.
[03:28] They totally match each other and are completely compatible.
[03:31] And so I can say like, you know,
[03:32] if I call it a couple times here,
[03:34] I can verify just the same sort of thing, you know.
[03:36] Make sure it's called with a string and that'll pass.
[03:39] But if I say, like I've got additional cool stuff,
[03:41] like if I said, "Make sure it's called exactly one time,"
[03:43] and that'll blow up
[03:44] 'cause we just called it twice at the top.
[03:46] So it'll say, "Cool messages here,
[03:47] "expected it to be called with one time,
[03:50] "was actually called this way two times."
[03:52] Very instructive because mocking is confusing.
[03:55] So if you are confused,
[03:57] I've got a method called "explain".
[03:59] You just pass it any mock
[04:00] and it'll return a double explanation.
[04:02] And so you can print out the message about it.
[04:04] It'll like give you a little text adventure saying:
[04:07] "Here, you know, this is a fake thing.
[04:08] "Here's all the mocked messages.
[04:11] "Here's all the stubbings
[04:11] "and here's all the actual calls."
[04:13] And then there's a reference object
[04:14] which returns a double data,
[04:16] which has all of this introspective data that you can use.
[04:18] And so metaprogramming is really scary,
[04:21] but it's important to have good introspection tools.
[04:24] And so you can answer all kinds of questions.
[04:26] Like for example, how many calls were there?
[04:28] There were three.
[04:29] How many times were the stubbing satisfied?
[04:30] There were two.
[04:31] So is that all?
[04:32] No, there's other stuff too.
[04:33] This supports a TDD Workflow.
[04:35] And so there's a cool method missing thing override
[04:37] that I did.
[04:38] So like, if you wanna add a method called "destroy",
[04:39] you just call it and then it'll print out here saying,
[04:41] "Hey do you want define that method?
[04:43] "Here's a little copy paste stub."
[04:45] And so you can just kinda paste it right in.
[04:47] So if you're in a creative mode, it makes it go fast.
[04:49] And then for dependency injection,
[04:51] you can just literally call
[04:54] another method called "Mocktail.of_next"
[04:56] and then pass it the class.
[04:58] And what that's gonna do is when I call "talk"
[05:00] it stubs the new method on the class.
[05:03] And now these two things are gonna
[05:04] be the exact same mock instance.
[05:06] So I don't have to make a goofy dependency injection API.
[05:08] It just works, it's really neat.
[05:09] So if you're mildly interested in this,
[05:11] you can find us on GitHub under testdouble/mocktail.
[05:15] It's a Portland friendly gem
[05:16] because it's only been downloaded 5,000 times.
[05:19] And so it's still very hip
[05:22] and I hope you all go and check it out.
[05:23] So thank you everyone for your time.
[05:25] Appreciate it.
[05:26] (audience applauds)

Related Insights

🔗
Please don't mock me
🔗
My favorite way to TDD
🔗
Mock objects in discovery tests
🔗
Mocking callbacks: Speed up your TDD and test driven development

Explore our insights

See all insights
Developers
Developers
Developers
You’re holding it wrong! The double loop model for agentic coding

Joé Dupuis has noticed an influx of videos and blog posts about the "correct" way of working with AI agents. Joé thinks most of it is bad advice, and has a better approach he wants to show you.

by
Joé Dupuis
Leadership
Leadership
Leadership
Don't play it safe: Improve your continuous discovery process to reduce risk

We often front-load discovery to feel confident before building—but that’s not real agility. This post explores how continuous learning reduces risk better than perfect plans ever could.

by
Doc Norton
Leadership
Leadership
Leadership
How an early-stage startup engineering team improved the bottom line fast

A fast-growing startup was burning cash faster than it could scale. Here’s how smart engineering decisions helped them improve the bottom line.

by
Jonathon Baugh
Letter art spelling out NEAT

Join the conversation

Technology is a means to an end: answers to very human questions. That’s why we created a community for developers and product managers.

Explore the community
Test Double Executive Leadership Team

Learn about our team

Like what we have to say about building great software and great teams?

Get to know us
Test Double company logo
Improving the way the world builds software.
What we do
Services OverviewSoftware DeliveryProduct ManagementLegacy ModernizationDevOpsUpgrade RailsTechnical RecruitmentTechnical Assessments
Who WE ARE
About UsCulture & CareersGreat CausesEDIOur TeamContact UsNews & AwardsN.E.A.T.
Resources
Case StudiesAll InsightsLeadership InsightsDeveloper InsightsProduct InsightsPairing & Office Hours
NEWSLETTER
Sign up hear about our latest innovations.
Your email has been added!
Oops! Something went wrong while submitting the form.
Standard Ruby badge
614.349.4279hello@testdouble.com
Privacy Policy
© 2020 Test Double. All Rights Reserved.