tags:

views:

40

answers:

2

In the situation below the @crawl object DOES RECEIVE the crawl call, but the method mock fails ie: the method is not mocked.

Does Thread somehow create its own copy of the @crawl object escaping the mock?

  @crawl.should_receive(:crawl).with(an_instance_of(String)).twice.and_return(nil)

  threads = @crawl.create_threads

thread creation code:

  def crawl(uri)
    dosomecrawling
  end

  def create_threads
    (1..5).each do
      Thread.new do
        crawl(someurifeedingmethod)
      end
    end
  end
+1  A: 

This code works perfectly.

You can add 5 times the expects.


class Hello
  def crawl(uri)
    puts uri 
  end 

  def create_threads
    (1..5).each do
      Thread.new do
        crawl('http://hello')
      end 
    end 
  end 
end

describe 'somting' do
  it 'should mock' do
    crawl = Hello.new
    5.times do
      crawl.should_receive(:crawl).with(an_instance_of(String)).and_return(nil)
    end                                                                                                                                   
    threads = crawl.create_threads
  end 
end

shingara
A: 

It does not appear from the code posted that you are joining the threads. If so, there is a race condition: Sometimes the test will execute with some or all of the threads not having done their job; The fix is along these lines:

!/usr/bin/ruby1.9

class Crawler

  def crawl(uri)
    dosomecrawling
  end

  def create_threads
    @threads = (1..5).collect do
      Thread.new do
        crawl(someurifeedingmethod)
      end
    end
  end

  def join
    @threads.each do |thread|
      thread.join
    end
  end

end

describe "the above code" do

  it "should crawl five times" do
    crawler = Crawler.new
    uri = "uri"
    crawler.should_receive(:someurifeedingmethod).with(no_args).exactly(5).times.and_return(uri)
    crawler.should_receive(:crawl).with(uri).exactly(5).times
    crawler.create_threads
    crawler.join
  end

end
Wayne Conrad