[ruby-list:50617] Kernel.open の stub 方法

From: UEDA Hiroyuki <bsdmad@...>
Date: 2017-12-09 12:44:58 UTC
List: ruby-list #50617
うえだ と申します。

Rails で Redmine からチケットを一括取得して処理するコードを書いています。
動作自体は想定通りなのですが、これをテストすべく mocha を使って Kernel の
open メソッドを stub 化してみたものの、自分が思ったようになりません。

コードは以下のようになっています(抜粋です)。


---------- lib/interfaces/redmine/base.rb ----------
# coding: utf-8
#
require 'open-uri'
require 'net/http'
require 'json'
require 'date'

module Interfaces
  module Redmine
    class Base

      def self.search(uri, target, offset = -100, limit = 100)
        list        = []
        total       = nil
        max_threads = 8
        threads     = []
        m           = Mutex.new

        max_threads.times do |num_thread|
          threads << Thread.start(num_thread) do |i|
            while true
              m.synchronize { offset += limit }
              break if total && offset > total

              open("#{URL}/#{uri}&amp;key=#{API_KEY}&amp;include=relations&amp;offset=#{offset}&amp;limit=#{limit}")
{ |io|
                data = JSON.parse(io.read)
                list << data[target]
                total = data["total_count"]
              }
              raise "Too many threads" if offset > 999999
            end
          end
        end
        threads.each {|th| th.join}

        list.flatten
      end
    end
  end
end
-------------------------------------------------------------------------

---------- test/lib/interfaces/redmine/base_test.rb ----------
# coding: utf-8
require 'test_helper'

class RedmineBaseTest < ActiveSupport::TestCase
  test 'should search correclty' do
    data = {total_count: 10, issues: %w(a b c d e f g h i j)}.to_json
    OpenURI.stubs(:open_uri).returns(StringIO.new(data))

    puts data

    assert_equal data['issues'],
Interfaces::Redmine::Base.search('/projects/test', 'issues')
  end
end
-------------------------------------------------------------------------

これを実行すると、stub によって実際の Redmine サーバへのアクセスは
行われないものの、open した結果が何も返ってこないために exception が
raise されてしまいます。

$ bin/rake test TEST="test/lib/interfaces/redmine/base_test.rb"
Running via Spring preloader in process 51657
Loaded suite test
Started
.........................................{"total_count":10,"issues":["a","b","c","d","e","f","g","h","i","j"]}
E
====================================================================================================
Error: test: should search correclty(RedmineBaseTest): RuntimeError:
Too many threads
/path/to/project/lib/interfaces/redmine/base.rb:37:in `block (2
levels) in search'
====================================================================================================
........................................................................


お分かりになるがいらっしゃいましたら、私が想定しているテストケースを
パスさせるような stub の書き方(の問題でしょうか…?)をご教示いただ
ければ幸いです。


どうぞよろしくお願いいたします。


-- 
UEDA "BSD mad" Hiroyuki <bsdmad@gmail.com>

In This Thread

Prev Next