📖 Scenario: You are writing tests for a simple Ruby program that fetches weather data from an external service. Since the real service is slow and unreliable for testing, you will use mocking and stubbing to simulate its behavior.
🎯 Goal: Build a test that uses mocking and stubbing to simulate the weather service response and verify your program handles it correctly.
📋 What You'll Learn
Create a class WeatherService with a method fetch_temperature(city) that normally returns a temperature.
Create a test class WeatherServiceTest using minitest.
Stub the fetch_temperature method to return a fixed value for testing.
Mock the fetch_temperature method call and verify it was called with the correct argument.
💡 Why This Matters
🌍 Real World
Mocking and stubbing help you test your code without relying on slow or unreliable external services, making tests faster and more reliable.
💼 Career
Many software development jobs require writing automated tests. Knowing how to mock and stub is essential for testing code that interacts with external systems.
Progress0 / 4 steps
1
Create the WeatherService class
Create a class called WeatherService with a method fetch_temperature(city) that returns the string "Real temperature for #{city}".
Ruby
Hint
Define a class and a method that returns a string including the city name.
2
Set up the test class with minitest
Create a test class called WeatherServiceTest that inherits from Minitest::Test. Inside it, create a method setup that initializes an instance variable @service as a new WeatherService.
Ruby
Hint
Use require 'minitest/autorun' and define a test class inheriting from Minitest::Test.
3
Stub the fetch_temperature method
Inside WeatherServiceTest, add a test method called test_stub_fetch_temperature. In it, stub the fetch_temperature method on @service to always return "Stubbed temperature 25C" when called with any city. Then call @service.fetch_temperature('London') and assign the result to temp.
Ruby
Hint
Use object.stub :method, return_value do ... end to stub a method temporarily.
4
Mock the fetch_temperature method call
Add a test method called test_mock_fetch_temperature_called_with_city inside WeatherServiceTest. Use Minitest::Mock to create a mock object. Expect the fetch_temperature method to be called once with argument 'Paris' and return "Mocked temperature 20C". Replace @service with the mock, call @service.fetch_temperature('Paris'), and verify the mock.
Ruby
Hint
Create a Minitest::Mock object, set an expectation with expect, and call verify to check it.
Practice
(1/5)
1. What is the main purpose of stubbing in Ruby testing?
easy
A. To check if a method was called with specific arguments
B. To slow down tests by adding delays
C. To run the actual method code during tests
D. To replace a method's return value with a fake one
Solution
Step 1: Understand stubbing concept
Stubbing means replacing a method's output with a fake value to control test behavior.
Step 2: Differentiate from mocking
Mocking checks method calls, but stubbing focuses on return values.
Final Answer:
To replace a method's return value with a fake one -> Option D
Quick Check:
Stubbing = fake return value [OK]
Hint: Stubs fake returns; mocks check calls [OK]
Common Mistakes:
Confusing stubs with mocks
Thinking stubs run real code
Believing stubs slow tests
2. Which of the following is the correct syntax to stub a method foo on an object obj to return 42 using RSpec?
easy
A. allow(obj).to receive(:foo).and_return(42)
B. expect(obj).to stub(:foo).and_return(42)
C. obj.stub(:foo).returns(42)
D. mock(obj).expects(:foo).returns(42)
Solution
Step 1: Recall RSpec stubbing syntax
In RSpec, stubbing uses allow(object).to receive(:method).and_return(value).
Step 2: Check each option
allow(obj).to receive(:foo).and_return(42) matches correct syntax; others use outdated or incorrect methods.
Final Answer:
allow(obj).to receive(:foo).and_return(42) -> Option A
Quick Check:
RSpec stub = allow + receive + and_return [OK]
Hint: Use allow(obj).to receive(:method).and_return(value) [OK]
Common Mistakes:
Using deprecated stub syntax
Confusing expect with allow for stubs
Using mock instead of allow for stubs
3. What will be the output of this Ruby code using RSpec mocks?
class Calculator
def add(a, b)
a + b
end
end
calc = Calculator.new
allow(calc).to receive(:add).with(2, 3).and_return(10)
puts calc.add(2, 3)
puts calc.add(4, 5)
medium
A. 10
10
B. 10
9
C. 5
9
D. 5
5
Solution
Step 1: Analyze stubbed method call
The method add is stubbed to return 10 only when called with arguments 2 and 3.
Step 2: Check calls and outputs
First call calc.add(2, 3) returns 10 due to stub. Second call calc.add(4, 5) is not stubbed, so runs original method returning 9.
Final Answer:
10
9 -> Option B
Quick Check:
Stubbed args return 10; others run real method [OK]
Hint: Stub affects only specified arguments [OK]
Common Mistakes:
Assuming all calls return stub value
Ignoring method arguments in stub
Expecting syntax error
4. Identify the error in this RSpec mocking code:
user = double('User')
expect(user).to receive(:login).with('admin')
user.login('guest')
medium
A. Missing stub for login method
B. The double is not created correctly
C. The method login is called with wrong argument
D. No error, code is correct
Solution
Step 1: Understand the expectation
The test expects login to be called with argument 'admin'.
Step 2: Check actual method call
The method is called with 'guest', which does not match the expectation.
Final Answer:
The method login is called with wrong argument -> Option C
Quick Check:
Expect argument mismatch causes failure [OK]
Hint: Match expected arguments exactly in mocks [OK]
Common Mistakes:
Calling method with different arguments
Confusing stub and expect syntax
Ignoring error raised by RSpec
5. You want to test a method that calls an external API method fetch_data on a Service object. How can you use mocking and stubbing together to test your method without calling the real API?
hard
A. Stub fetch_data to return fake data and mock to check it was called once
B. Call the real fetch_data method and ignore mocking
C. Mock fetch_data without stubbing its return value
D. Do not use mocking or stubbing; test with real API
Solution
Step 1: Stub the API call to avoid real network
Stub fetch_data to return controlled fake data, so tests run fast and reliably.
Step 2: Mock to verify the method call
Use mock to check fetch_data was called exactly once, ensuring your method triggers it.
Final Answer:
Stub fetch_data to return fake data and mock to check it was called once -> Option A
Quick Check:
Stub return + mock call count = test isolation [OK]
Hint: Stub return and mock call count together [OK]
Common Mistakes:
Calling real API in tests
Mocking without stubbing return value
Ignoring call verification
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.