Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RSpec: Testing with Threads

In RSpec, I have function that creates a new thread, and inside that thread performs some action–in my case, calls TCPSocket#readline. Here's the function as it is right now:

def read
  Thread.new do
    while line = @socket.readline
      #TODO: stuff
    end
  end
end

Due to thread scheduling, my test will fail if written as such:

it "reads from socket" do
  subject.socket.should_receive(:readline)
  subject.read
end

Currently the only way I know to hack around this is to use sleep 0.1. Is there a way to properly delay the test until that thread is running?

like image 370
Nick Acker Avatar asked Jan 30 '13 01:01

Nick Acker


2 Answers

If your goal is to assert the system state is changed by the execution of your second thread, you should join on the second thread in your main test thread:

it "reads from socket" do
  subject.socket.should_receive(:readline)
  socket_thread = subject.read
  socket_thread.join
end
like image 196
Winfield Avatar answered Nov 12 '22 17:11

Winfield


This is a bit of a hack, but here's a before block you can use in case you'd like the thread to yield but be able to call join at the end of the thread.

before do
  allow(Thread).to receive(:new).and_yield.and_return(Class.new { def join; end }.new)
end
like image 5
Trevor Turk Avatar answered Nov 12 '22 17:11

Trevor Turk