Reputation: 1383
Say I have this class:
class MyQueue
def initialize
@queue = Queue.new
end
def push(line)
@queue.push(line)
end
end
How should I test that instance variable @queue will receive push method when I call for push on MyQueue instance?
I tried this so far:
describe MyQueue do
let(:my_queue) { instance_double('MyQueue') }
let(:message_line) { double('message_line') }
describe '#push' do
before do
instance_queue = my_queue.instance_variable_set(:@queue, double)
allow(instance_queue).to receive(:push) { message_line }
end
it 'adds line to the queue' do
expect(my_queue.instance_variable_get(:@queue)).to receive(:push) { message_line }
my_queue.push(message_line)
end
end
end
But getting error:
#<InstanceDouble(MyQueue) (anonymous)> received unexpected message :push
with (#<Double "message_line">)
What am I doing wrong?
Upvotes: 2
Views: 5812
Reputation: 15781
You are creating double of MyQueue
class but you do not specify that it is allowed to receive #push
, that's why it fails on my_queue.push(message_line)
line.
In fact, you are going in wrong direction. You want to test a method of the MyQueue
class, which uses Queue
instance. What you want to do is to stub everything related to the interaction with Queue
, but you instead mock MyQueue
instance(my_queue
) making it dummy(and so, making all calls to it, including #push
, which you want to test, dummy).
Here is how I see it should be tested:
describe MyQueue do
let(:queue) { instance_double('Queue') }
let(:message_line) { double('message_line') }
describe '#push' do
before do
allow(Queue).to receive(:new).and_return(queue)
allow(queue).to receive(:push).with(message_line)
end
it 'adds line to the queue' do
expect(queue).to receive(:push).with(message_line)
MyQueue.new.push(message_line)
end
end
end
Finished in 0.00575 seconds (files took 0.27625 seconds to load)
1 example, 0 failures
Upvotes: 4