2014-11-24 46 views
0

我正在爲JRuby中的JDBC編寫一個簡單的包裝器。基本上我想要一個包裝類DBW,它需要一個連接字符串和一個可選的初始化塊。使用RSpec-mock模擬JRuby中的Java接口

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 

但是在我的測試中,我想用一個測試雙象,與DriverManager註冊Driver,所以我做了一個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調用。任何想法我失蹤?

回答

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[[email protected]], driver[[email protected]]] 
puts java.sql.DriverManager.getDrivers.to_a.inspect # does not return the mock_driver 
# [#<Java::SunJdbcOdbc::JdbcOdbcDriver:0x55974e79>] 

我建議你重構你的代碼不緊DriverManager太多.. 。或者簡單地用一個「真正的」(Java)模擬驅動程序編譯成一個.jar文件,並將其添加到類路徑