9

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?

2 Answers 2

13

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

2 Comments

Good call, in my n00bishness I completely forgot about the fact that it was returning the thread, so I didn't think to use it that way.
And what if the goal is not to wait on the thread to complete? Sort of like this: ruby-forum.com/topic/2477428 or alternate post code.activestate.com/lists/ruby-talk/20264
6

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

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.