问题描述
我无法模拟 connection.prepareCall("{call myStoreProcedure()}");调用 spring boot 项目。
每次我收到“org.h2.jdbc.JdbcsqlSyntaxErrorException:未找到列“myStoreProcedure”;sql 语句:”,因为我使用的是 h2 数据库和我们没有那个程序。但是当我模拟它不应该调用数据库时它应该只返回模拟值......但它没有发生。
注意:我遇到了异常但我的测试用例正在通过。
下面是我的代码片段:
package com.khan;
import static org.mockito.Mockito.mock;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import javax.sql.DataSource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.powermock.api.mockito.powermockito;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.powermockrunner;
import org.powermock.modules.junit4.powermockrunnerDelegate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBoottest;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(powermockrunner.class)
@powermockrunnerDelegate(SpringJUnit4ClassRunner.class)
@PrepareForTest({ DataSource.class,Connection.class,CallableStatement.class })
@SpringBoottest
@PowerMockIgnore({ "javax.management.*","javax.net.ssl.*","javax.security.auth.*" })
@TestPropertySource({ "classpath:application.properties" })
public class MainClasstest {
@Autowired
MainClass mainClass;
@Autowired
private DataSource dataSource;
@Test
public void testMethod() throws Exception {
ResultSet resultSet = mock(ResultSet.class);
CallableStatement callableStatement = mock(CallableStatement.class);
Mockito.when(dataSource.getConnection()).thenReturn(connection);
Mockito.when(connection.prepareCall("{ call myprocedure()}")).thenReturn(callableStatement);
Mockito.when(callableStatement.executeQuery()).thenReturn(resultSet);
//Tried below one as well but no luck
//powermockito.stub(powermockito.method(Connection.class,"prepareCall",Mockito.any())).toReturn(callableStatement);
mainClass.callProcedure("Procedure Name");
}
}
下面是我的主类:
public class MainClass{
@Autowired
private DataSource dataSource;
public void callProcedure(String storedProcName) throws sqlException {
Connection connection = dataSource.getConnection();
try (CallableStatement cs = connection.prepareCall("{call " + storedProcName + "}");) { // I am getting exception here but test cases are passing
cs.executeQuery();
} catch (sqlException e) {
log.error("Exception occured while execution of stored procedure having storedProcName: {} with reason: {} "
+ e.getMessage(),storedProcName,e);
throw e;
}
}
}
解决方法
我发现您的测试用例中有很多问题。
-
不需要加载 Spring Context 来测试这个类。 Mock 应该就够了。
-
在您的 callProcedure 中,您正在传递 "Procedure Name" 但在模拟中,您期望 "{ call myprocedure()}" 以便模拟永远不会被触发.
-
您的测试用例通过,因为您没有验证任何内容。
尝试如下操作。
@RunWith(PowerMockRunner.class)
public class MainClassTest {
@InjectMocks
MainClass mainClass;
@Mock
private DataSource dataSource;
@Test
public void testMethod() throws Exception {
//Given
ResultSet resultSet = mock(ResultSet.class);
CallableStatement callableStatement = mock(CallableStatement.class);
Mockito.when(dataSource.getConnection()).thenReturn(connection);
Mockito.when(connection.prepareCall(anyString())).thenReturn(callableStatement);
Mockito.when(callableStatement.executeQuery()).thenReturn(resultSet);
//When
mainClass.callProcedure("Procedure Name");
//Then
verify(dataSource,times(1)).getConnection();
}
}