我希望单元测试一个签名为
的方法public oracle.sql.ARRAY methodA(java.sql.Connection connection)
使用
模拟连接对象Mockito.mock(Connection.class)
并在测试时传递给methodA。
oracle.sql.ARRAY有一个构造函数
new ARRAY(oracle.sql.ArrayDescriptor, Connection, Object)
methodA具有获取ArrayDescriptor的逻辑。 它还具有为此构造函数提供第三个参数的逻辑,但它将其作为Objects
的数组提供我正在模拟这两组逻辑并传递一个模拟的ArrayDescriptor对象和一个模拟的Object数组。 所有这些嘲弄工作都正确。
所以我的构造函数调用就像
new ARRAY(arrayDescriptorMock, connectionMock, objectMock)
此构造函数调用在作为测试
的一部分执行时抛出异常java.lang.ClassCastException:$ $$ java.sql.Connection中$$ EnhancerByMockitoWithCGLIB 2427854e 无法转换为oracle.jdbc.OracleConnection
我做了很多尝试来模拟这个构造函数调用以避免这个错误。然而,每一个都证明是徒劳的。我正在记录构造函数的模拟代码
Attempt1
PowerMockito.whenNew(ARRAY.class).withParameterTypes(ArrayDescriptor.class, Connection.class, Object.class)
.withArguments(any(ArrayDescriptor.class), any(Connection.class), any(Object[].class))
.thenReturn(expectedArray);
ATTEMPT2
PowerMockito.whenNew(ARRAY.class).withArguments(arrayDescriptorMock,connectionMock,objectArrayMock).thenReturn(expectedArray);
图例: arrayDescriptorMock:ArrayDescriptor的模拟
connectionMock:连接模拟
objectArrayMock:模拟代码为
的对象数组的模拟 Object[] structArrayMock = new Object[2];
STRUCT obj1 = mock(STRUCT.class);
STRUCT obj2 = mock(STRUCT.class);
structArrayMock[0] = obj1;
structArrayMock[1] = obj2;
注意: 测试中的方法有以下代码,我没有模拟
Object[] objArray = new Object[2];
我正在使用PowerMockito,Mockito和TestNG。但是,我认为这个问题与TestNG无关,因此JUNIT标签应该没问题。
请告知为什么会出现这种ClassCastException以及如何避免它?
修改 我也相信Mockito假设拦截构造函数调用。这意味着它不应该允许执行真正的构造函数。假设只返回ARRAY类的模拟对象。为什么不会发生这种情况?为什么要尝试施放?
答案 0 :(得分:2)
答案的开头是在例外的直接消息中。
... cannot be cast to oracle.jdbc.OracleConnection
代码显示来自oracle驱动程序的oracle.sql.ARRAY
对象不接受实现JDBC接口的任何Object
(然后mocks ),例如{ {1}}。这是以任何方式预期的任何连接器架构,包括JDBC,因为它遵循JCA原则。
为什么会出现这种情况是因为来自JCA实现的对象需要在内部了解/与自己的对象进行交互。 java.sql.Connection
接口只是客户端必须存在的最小可用合约(此处为JDBC)。
因此,考虑到这一事实并且java.sql.Connection
是一个oracle驱动程序类型,那么预期此对象需要内部oracle.sql.ARRAY
才能正常运行。嘲an oracle.sql.Connection
的胜利甚至是好的oracle.jdbc.OracleConnection
可能会以超出预期的方式使用此类型,并最终导致地狱般的固定。
我们,模仿者,说:"不要嘲笑你不拥有的类型。这是不模仿ARRAY
的。但在这个测试中,我不明白为什么有人会测试由其他人编写的代码,特别是JDBC驱动程序,但如果其中一个实际上是驱动程序开发人员。
如果您需要测试DAO或存储库使用oracle.sql.Connection
,那么编写ARRAY
(使用真正的Oracle)会更合适。
为了回答这个意图,我想说肯定会去找IT。这就是原因:
实际上,测试代码在某些时候涉及专有类型。这些类型带有一个驱动程序,必须连接到真实数据库才能提供连接。我没有看到一种简单的单元测试方法,
Integration Tests
的模拟,但这会破坏此特定测试的目的我必须补充一点,第一个原因是当我的系统需要连接到另一个系统时,我总是编写集成测试的原因。 IT有助于覆盖应用程序边界,包括持久性。我通常调用存储库的业务API(这是具有面向业务的API的DAO),并且它们可以使用任何数据存储区来完成它们的工作。 Oracle或其他人可以更改驱动程序的实现,删除类型等。我不必重写这些测试,只需要实际实现。
答案 1 :(得分:2)
oracle.sql.ARRAY
需要oracle.jdbc.OracleConnection
查看ARRAY类的代码:
如果(!(paramArrayDescriptor.getInternalConnection()。isDescriptorSharable(((oracle.jdbc.OracleConnection)paramConnection).physicalConnectionWithin()))){ 抛出新的SQLException("无法构造ARRAY实例,无效 连接&#34); }
因此,当您尝试提供由PowerMockito模拟的java.sql.Connection
时,无法在oracle.jdbc.OracleConnection
中投放。
所以使用这个 -
Connection conn = PowerMockito.mock(OracleConnection.class);