Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
Building A Simple Mocking Library in Ruby #2
This tutorial is based on Andy Lindeman's awesome talk — Building a Mocking Library presented at Ancient City Ruby 2013. This is not a direct transcript of the video, but the code presented is almost the same (with minimal changes).
In his talk, Andy showed us how we can build a Mocking library for Minitest with just basic knowledge of Ruby and I felt that it's actually a great way to learn Ruby! So I decided to document the talk in writing and share it up here on the blog so that we can all learn together.
We are going to implement a simple Mocking library for Minitest.
Given an object:
# Test double object = Object.new
We should be able to stub a method on this object and it will return our stubbed value:
# Stub allow(object).to receive(:full?).and_return(true) object.full? # => true
We should be able to mock an object (mock will verify if
# Mock item_id = 1234 assume(object).to receive(:remove).with(item_id)
Why don't we use
We will have two main classes -
Remember our Goal? In order to be able to do this:
We'll break them up as follows using our two main classes:
allow(w).to receive(:full?).and_return(true) ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #<StubTarget> #<ExpectationDefinition>
Enough Ruby that You Need to Know
How does Ruby find methods? It climbs up the ancestors chain! When you invoke
Ruby: Hey, do you have
Then it returns the result of
> object = Object.new => #<Object:0x007fc0223b8280> > object.to_s => "#<Object:0x007fc0223b8280>"
If Ruby can't find the method you want to call, it will climb up the ancestors chain, till it finds a class that responds to the message, otherwise it eventually throws a
object.class.ancestors => [Object, Kernel, BasicObject] # (searching from left to right)
Define a Method for a Specific Object
Ruby has a singleton class for every object and you can define a method in the singleton class.
The singleton class might be not visible in the ancestors chain above, but it's there.
The "Singleton Class" is easily confused with the Singleton design pattern.
In fact, singleton class is an anonymous class attached to a specific object. Best illustrated with an example:
object = Object.new def object.hello_world "Hello, World!" end object.hello_world # => "Hello, World!" another_object = Object.new object.hello_world # => NoMethodError (2)
In the example above, we are adding a
As you can see, Ruby insert the