2

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?

1 Answer 1

4

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
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.