我正在为以下方法编写TestCase
@Repository
public class CustomerContactDaoImpl implements CustomerContactDao {
@Autowired
@Qualifier(value = "dcv_jdbc_template")
private JdbcTemplate jdbcTemplate;
@Override
public void insertCustomer(Contact contact) {
SimpleJdbcCall call = new SimpleJdbcCall(jdbcTemplate).withProcedureName("ins_customerinfo");
try {
call.execute(new MapSqlParameterSource().addValue("customerid", contact.getCustomerID())));
} catch (Exception e) {}
}
这是我的测试用例
@RunWith(PowerMockRunner.class)
public class CustomerContactDaoImplTest {
@InjectMocks
CustomerContactDaoImpl customerContactDaoImpl;
@Before
public void init() {
MockitoAnnotations.initMocks(this);
}
@Test
public void insertCustomerContactTest() throws Exception {
Contact contact = Mockito.mock(Contact.class);
JdbcTemplate jdbcTemplateMock = Mockito.mock(JdbcTemplate.class);
SimpleJdbcCall mockedSimpleJdbcCall = Mockito.mock(SimpleJdbcCall.class);
PowerMockito.whenNew(SimpleJdbcCall.class).withArguments(jdbcTemplateMock).thenReturn(mockedSimpleJdbcCall);
mockedSimpleJdbcCall.execute(new MapSqlParameterSource().addValue("customerid", contact.getCustomerID())));
customerContactDaoImpl.insertCustomerContact(contact);
}
}
我收到错误消息
当模拟JDBCTemplate时,未获得未指定数据源的错误
请让我知道如何解决此错误
org.powermock.reflect.exceptions.TooManyConstructorsFoundException: Several matching constructors found, please specify the argument parameter types so that PowerMock can determine which method you're referring to.
Matching constructors in class org.springframework.jdbc.core.simple.SimpleJdbcCall were:
org.springframework.jdbc.core.simple.SimpleJdbcCall( javax.sql.DataSource.class )
org.springframework.jdbc.core.simple.SimpleJdbcCall( org.springframework.jdbc.core.JdbcTemplate.class )
at org.powermock.reflect.internal.WhiteboxImpl.throwExceptionWhenMultipleConstructorMatchesFound(WhiteboxImpl.java:1723)
at org.powermock.reflect.internal.WhiteboxImpl.findUniqueConstructorOrThrowException(WhiteboxImpl.java:1097)
at org.powermock.api.mockito.internal.expectation.DefaultConstructorExpectationSetup.createNewSubstituteMock(DefaultConstructorExpectationSetup.java:94)
at org.powermock.api.mockito.internal.expectation.DefaultConstructorExpectationSetup.withArguments(DefaultConstructorExpectationSetup.java:54)
at com.nrg.bccd.dao.test.CustomerContactDaoImplTest.insertCustomerContactTest(CustomerContactDaoImplTest.java:71)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:68)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:310)
at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:88)
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:96)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:294)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegateImpl.java:127)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.java:82)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:282)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:86)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:49)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:207)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:146)
答案 0 :(得分:4)
紧密耦合使得很难在没有意外行为的情况下隔离测试此代码。
但是让我们在当前状态下进行测试。
@InjectMocks
被使用,
@InjectMocks
CustomerContactDaoImpl customerContactDaoImpl;
但是在测试中声明了手动模拟
JdbcTemplate jdbcTemplateMock = Mockito.mock(JdbcTemplate.class);
并用作参数匹配器
PowerMockito.whenNew(SimpleJdbcCall.class).withArguments(jdbcTemplateMock).thenReturn(mockedSimpleJdbcCall);
由于设置new SimpleJdbcCall(...
时使用的实例不是在进行测试时注入的实例,因此参数将不匹配,并且将创建SimpleJdbcCall
的实际实例,并且它将尝试使用嘲笑的JdbcTemplate
(而不是您嘲笑的那个)和bam,错误。
需要对测试进行重构,以验证运动后的预期行为。
@RunWith(PowerMockRunner.class)
@PrepareForTest(CustomerContactDaoImpl.class) //prepare the class creating the new instance
public class CustomerContactDaoImplTest {
@Mock
JdbcTemplate jdbcTemplateMock; //YOUR MOCK TO BE INJECTED
@InjectMocks
CustomerContactDaoImpl customerContactDaoImpl;
@Before
public void init() {
MockitoAnnotations.initMocks(this);
}
@Test
public void insertCustomerContactTest() throws Exception {
//Arrange
string paramName = "customerid";
string expected = "fakeCustomerIdHere"; //assumption made as to type;
Contact contact = Mockito.mock(Contact.class);
when(contact.getCustomerID()).thenReturn(expected);
SimpleJdbcCall mockedSimpleJdbcCall = Mockito.mock(SimpleJdbcCall.class);
when(mockedSimpleJdbcCall.withProcedureName(anyString()))
.thenReturn(mockedSimpleJdbcCall);
PowerMockito.whenNew(SimpleJdbcCall.class).withArguments(jdbcTemplateMock)
.thenReturn(mockedSimpleJdbcCall);
//Act
customerContactDaoImpl.insertCustomerContact(contact);
//Assert
verify(mockedSimpleJdbcCall).execute(any(MapSqlParameterSource.class));
verify(contact).getCustomerID();
}
}
答案 1 :(得分:0)
遵循Spring JDBC tests,首先模拟所有数据库对象:
@BeforeEach public void setUp() throws Exception { connection = mock(Connection.class); databaseMetaData = mock(DatabaseMetaData.class); dataSource = mock(DataSource.class); callableStatement = mock(CallableStatement.class); given(connection.getMetaData()).willReturn(databaseMetaData); given(dataSource.getConnection()).willReturn(connection); }
并在测试中使用它们:
@Test public void testAddInvoiceProcWithoutMetaDataUsingMapParamSource() throws Exception { initializeAddInvoiceWithoutMetaData(false); SimpleJdbcCall adder = new SimpleJdbcCall(dataSource).withProcedureName("add_invoice"); adder.declareParameters( new SqlParameter("amount", Types.INTEGER), new SqlParameter("custid", Types.INTEGER), new SqlOutParameter("newid", Types.INTEGER)); Number newId = adder.executeObject(Number.class, new MapSqlParameterSource(). addValue("amount", 1103). addValue("custid", 3)); assertThat(newId.intValue()).isEqualTo(4);