用rspecmock在JRuby中模拟Java接口
我正在用JRuby为JDBC编写一个过于简单的包装器。本质上,我想要一个包装类用rspecmock在JRuby中模拟Java接口,rspec,interface,mocking,jruby,rspec-mocks,Rspec,Interface,Mocking,Jruby,Rspec Mocks,我正在用JRuby为JDBC编写一个过于简单的包装器。本质上,我想要一个包装类DBW,它接受一个连接字符串和一个可选的初始化块 require 'java' class DBW def initialize (connection_string, &optional_init_block) if optional_init_block yield end @connection_string = conn
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
然而,在我的测试中,我想使用一个双重测试作为驱动程序
,该驱动程序注册到驱动程序管理器
,因此我在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)
如测试代码中所述,
DriverManager
没有调用acceptsURL方法。你知道我遗漏了什么吗?你很可能碰到了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>]
java.sql.DriverManager.class\u eval do
字段\u读取器:注册表地址
结束
# ...
Java::Java.sql.DriverManager.registerDriver(模拟驱动程序)
将java.sql.DriverManager.registeredDrivers.to#s#返回模拟#u驱动程序(最后一个)
#[driver[className=sun.jdbc.odbc。JdbcOdbcDriver@55974e79],driver[className=org.jruby.gen。InterfaceImpl1708146542@b02cbee]]
将java.sql.DriverManager.getDrivers.to_a.inspect#不返回模拟_驱动程序
# [#]
我建议您重构代码,使其与DriverManager
的关系不要太紧密。。。或者简单地尝试将编译成.jar的“真实”(Java)模拟驱动程序添加到类路径中