1

I have a section in my code which polls a queue for a message and then acts on it depending on the message type:

@queue = Foo::Queue.new
loop do
  @queue.poll do |message|                                                                                                                              
    if message[:task] == TAKEACTION
      result = takeaction(message)
      @queue.send_result(result, message)
    end
    @queue.pong(message) if message[:task] == PING
  end
end

How do I set up a test to supply a single message and verify that the @queue acts on it as I expect?

I have seen very little about testing blocks in minitest, and haven't found anything in ruby regarding breaking out of infinite loops, though I found one idea in python where you set up the second run to throw an exception.

Can any ruby / minitest gurus help?

egeland
  • 1,244
  • 1
  • 12
  • 19
  • Some tips [here](https://stackoverflow.com/questions/5717813/what-is-the-best-practice-when-it-comes-to-testing-infinite-loops). – Radi May 06 '15 at 06:42

1 Answers1

0

For minitest using a stub will work. The example below is self contained and can run on its own. You can send an exception as a lambda with a stub to break the infinite loop and continue testing.

# class receiving the messages from class being tested
class Obj
  def method_if_true
    # do some stuff
    return 'anything that is true'
  end

  def method_if_false
    # do some stuff
    false
  end
end

# class to be tested
class TestingLoop
  def initialize(args)
    @obj = args.fetch(:object, Obj.new)
    @bool = args[:bool]
  end

  def looping
    loop do
      if @bool
        @obj.method_if_true
        # @bool is true
      elsif !@bool
        @obj.method_if_false
        # @bool is false
      end
    end
  end
end

require 'minitest/autorun'
# class that tests
class TestTestingLoop < MiniTest::Test
  def setup
    @obj = Obj.new
    @raises_exception = lambda { raise RuntimeError.new }
    # could use the '->' syntax instead of the word lambda
  end

  def test_sends_correct_method_when_true
    @obj.stub :method_if_true, @raises_exception do
      testing_loop = TestingLoop.new({object: @obj, bool: true})
      assert_raises(RuntimeError) { testing_loop.looping }
    end
  end

  def test_sends_correct_method_when_false
    @obj.stub :method_if_false, @raises_exception do
      testing_loop = TestingLoop.new({object: @obj, bool: false})
      assert_raises(RuntimeError) { testing_loop.looping }
    end
  end
end
kaelhop
  • 401
  • 4
  • 5