What if you could test your code without waiting for slow or tricky parts every time?
Why Test doubles concept in Ruby? - Purpose & Use Cases
Imagine you are testing a car's braking system, but you have to test it on a real car every time. You need the car, the road, and a safe place to stop. This is like testing code that depends on other parts that are hard to use or slow.
Testing with real parts can be slow, risky, and sometimes impossible. You might wait a long time for a response or cause errors that are hard to fix. It's like waiting for a friend to answer the phone every time you want to talk.
Test doubles act like pretend parts or friends. They stand in for the real things during tests, so you can check your code quickly and safely without needing the real parts every time.
real_car.brake assert real_car.stopped?
fake_car = TestDouble.new fake_car.brake assert fake_car.stopped?
It lets you test your code faster and more reliably by using simple stand-ins instead of the real, complex parts.
When building a website that sends emails, you don't want to send real emails every time you test. Using test doubles, you can pretend to send emails and check if your code tries to send them correctly.
Manual testing with real parts is slow and risky.
Test doubles replace real parts with simple stand-ins.
This makes testing faster, safer, and easier to control.
Practice
What is the main purpose of using test doubles in Ruby testing?
Solution
Step 1: Understand what test doubles do
Test doubles are fake objects used in tests to replace real parts of the program.Step 2: Identify the main goal
The goal is to isolate the part being tested by removing outside effects from real objects.Final Answer:
To replace real objects with fake ones to isolate tests -> Option CQuick Check:
Test doubles isolate tests = A [OK]
- Thinking test doubles speed up production code
- Believing test doubles permanently change classes
- Confusing test doubles with UI tools
Which of the following is the correct way to create a test double named user in Ruby using RSpec?
?Solution
Step 1: Recall RSpec syntax for test doubles
RSpec uses the methoddoubleto create test doubles.Step 2: Match the correct method call
The correct syntax isdouble('name'), sodouble('user')is right.Final Answer:
user = double('user') -> Option BQuick Check:
RSpec double creation = A [OK]
- Using fake or stub instead of double
- Confusing mock_object with double
- Missing quotes around the name
What will be the output of this Ruby code using a test double?
user = double('user')
allow(user).to receive(:name).and_return('Alice')
puts user.nameSolution
Step 1: Understand the double setup
The doubleuseris told to respond tonamewith 'Alice'.Step 2: Check the method call output
Callinguser.namereturns 'Alice' as set byand_return.Final Answer:
Alice -> Option AQuick Check:
Double returns stubbed value = C [OK]
- Expecting the double name instead of stubbed return
- Thinking it returns nil by default
- Assuming NoMethodError without stub
Identify the error in this test double usage and how to fix it:
order = double('order')
allow(order).to receive(:total)
puts order.totalSolution
Step 1: Analyze the stub setup
The methodtotalis allowed but no return value is set, so it returns nil.Step 2: Fix by adding return value
Addand_return(value)to specify whattotalshould return.Final Answer:
Missingand_returncausesorder.totalto return nil, fix by addingand_return-> Option AQuick Check:
Stub needs return value = B [OK]
- Thinking double name must be symbol
- Confusing allow with expect usage
- Forgetting to print output
You want to test a PaymentProcessor class that calls an external Gateway service. How can you use a test double to ensure your test does not call the real Gateway?
class PaymentProcessor
def initialize(gateway)
@gateway = gateway
end
def pay(amount)
@gateway.charge(amount)
end
end
# Test code here?Solution
Step 1: Understand dependency injection
ThePaymentProcessortakes agatewayobject to callcharge.Step 2: Use a test double for gateway
Create a double that expectschargewith the amount and returns true to simulate success.Step 3: Avoid calling real external service
This prevents the test from calling the realGateway, isolating the test.Final Answer:
Create a double forgatewaythat expectschargewith amount and returns true -> Option DQuick Check:
Use doubles to isolate external calls = D [OK]
- Calling real external services in tests
- Hardcoding dependencies inside classes
- Using allow_any_instance_of unnecessarily
Ready to prove it?
Pass the test and this pattern moves unknown
