0

JRuby で JDBC の単純なラッパーを作成しています。基本的にDBW、接続文字列とオプションの初期化ブロックを受け取るラッパー クラスが必要です。

require 'java'

class DBW
    def initialize (connection_string, &optional_init_block)
        if optional_init_block
            yield
        end

        @connection_string = connection_string
    end
    def get_connection
        Java::java.sql.DriverManager.getConnection(@connection_string)
    end
end

ただし、私のテストでは、Driverに登録するテスト ダブルを使用したいDriverManagerので、RSpec テストで次のことを行いました。

it "can produce a connection using the connection string" do 

    mock_conn = instance_double("Connection") # A dummy connection instance
    mock_driver = instance_double("Driver")
    allow(mock_driver).to receive(:acceptsURL).with(any_args) {
        # this doesn't get called when the wrapper calls getConnection on the DriverManager 
        true
    }
    # Expecting that connect would be called on the driver with the connecion string...
    allow(mock_driver).to receive(:connect).with(any_args).and_return(mock_conn)

    wrapper = DBW.new "jdbc:subprotocol:subname" do 
        # Initialize the DriverManager with the mock driver
        Java::java.sql.DriverManager.registerDriver(mock_driver)
    end

    # This should call in to DriverManager.getConnection
    conn = wrapper.get_connection
    expect(conn).to eq(mock_conn)

end

テストを実行すると、次のエラーが表示されます。

Failures:

  1) DBW can produce a connection using the connection string
     Failure/Error: Unable to find matching line from backtrace
     Java::JavaSql::SQLException:
       No suitable driver found for jdbc:subprotocol:subname
     # java.sql.DriverManager.getConnection(java/sql/DriverManager.java:689)
     # java.sql.DriverManager.getConnection(java/sql/DriverManager.java:270)
     # java.lang.reflect.Method.invoke(java/lang/reflect/Method.java:497)
     # RUBY.get_connection(/playground/dbw.rb:12)
     # RUBY.(root)(/playground/specs/dbw_spec.rb:39)

テスト コードに示されているように、acceptsURL メソッドは によって呼び出されませんDriverManager。私が見逃しているアイデアはありますか?

4

1 に答える 1

1

あなたはあなたjava.sql.DriverManagerを台無しにしているように見える内部にぶつかる可能性が非常に高いです. .java ソースを見ると、呼び出し元のローダーで接続を取得するときにチェックがあることがわかります (呼び出し前connect-acceptsURLここでは関係ありません)。これは JRuby 内で爆発する可能性があるため、java.sql.Driver生成されたインスタンスが存在することを確認できますが、API を使用すると返されません。

java.sql.DriverManager.class_eval do
  field_reader :registeredDrivers
end

# ...

Java::java.sql.DriverManager.registerDriver(mock_driver)

puts java.sql.DriverManager.registeredDrivers.to_s # returns the mock_driver (last)
# [driver[className=sun.jdbc.odbc.JdbcOdbcDriver@55974e79], driver[className=org.jruby.gen.InterfaceImpl1708146542@b02cbee]]
puts java.sql.DriverManager.getDrivers.to_a.inspect  # does not return the mock_driver
# [#<Java::SunJdbcOdbc::JdbcOdbcDriver:0x55974e79>]

コードをリファクタリングして、きつくなりDriverManagerすぎないようにすることをお勧めします...または、クラスパスに追加された.jarにコンパイルされた「実際の」(Java)モックドライバーを試してみてください

于 2014-11-24T09:45:45.713 に答える