- Read Tutorial
- Watch Guide Video
In this guide, we are going to create a RSpec stub for sending a SMS message, and this requires a decent amount of configuration. I'm going to open my guide and we'll go through each step.
First off, we are going to create a mock or fake stub. This is important, especially if your application is going to contact an outside API for implementing its functionality. Frequent contacts to APIs will slow your test, and it can sometimes even block you out, especially if you reach your usage limit. Let's say, for example, you're allowed only hundred API calls a day. When you run ten tests, you'll reach that limit in no time, and cannot test further. Additionally, you'll never be able to work offline if you use real test stubs. To avoid these problems, it's always good to have mock or fake stubs.
Create a file called fake_sms.rb
in your lib
folder and have this code:
# lib/fake_sms.rb module FakeSms Message = Struct.new(:message, :message) @messages = [] def self.send_sms(number:, message:) @messages << Message.new(number, message) end def self.messages @messages end end
Here, we are creating a module called FakeSms
, and using a data structure called Struct
. This Struct
object is the best way to mimic a database. We are passing the number and message as its arguments.
When we run this module, we are going to create an object called a Message
that comes with a number and message every time and pass it to an array called messages
. Later, our tests can see what's inside messages
.
Next, let's config our rspec
tests. Open spec_helper.rb
in your spec
folder, as this is where we put all configuration information. I want to remove all the comments before adding the code because I think it's confusing.
Let's add the new code.
# spec/spec_helper.rb RSpec.configure do |config| config.expect_with :rspec do |expectations| expectations.include_chain_clauses_in_custom_matcher_descriptions = true end config.mock_with :rspec do |mocks| mocks.verify_partial_doubles = true end config.before(:each) do stub_const("SmsTool", FakeSMS) end config.shared_context_metadata_behavior = :apply_to_host_groups end
In this code, we are saying that before each config, we are going to stub the constant SmsTool
for a FakeSMS
. Essentially, we are asking the tests to check before running everything if there is a call to SmsTool
, and if there is a call, we want the test to swap SmsTool
with FakeSMS
. If you see, we have a method called send_sms
in our FakeSMS
module, just like our SmsTool
to mimic this functionality.
Next, let's test it out on our test environment in the Rails console. You can do that with the command:
rails c -e test
We are going to replicate exactly what we did in the previous lesson to see if the mock is working. So, the command will be:
Let's run our FakeSMS
module with this command:
FakeSMS.send_sms(number: 234234, message: "asdfasdf")
See how this struct
acts as a database to store multiple messages. This is the closest we are going to get to mimicking an API call.