[英]How to Mock Spring JDBCTemplate execute method in Junit Test case
當我執行第二個測試 testExecute_noException 時,仍然返回 null 指針異常。 對於第一個測試返回 null 指針異常是有效的,但對於第二個測試我需要繼續下一行測試。 請參閱下面的更多詳細信息。
實際代碼:
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.jdbc.core.JdbcTemplate;
import javax.sql.DataSource;
public class SimpleQueryExecutorTasklet implements Tasklet {
private DataSource dataSource;
private String sql;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public void setSql(String sql) {
this.sql = sql;
}
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
new JdbcTemplate(this.dataSource).execute(this.sql);
return RepeatStatus.FINISHED;
}
}
測試代碼:
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
import org.powermock.api.mockito.PowerMockito;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.jdbc.core.JdbcTemplate;
import javax.sql.DataSource;
@RunWith(MockitoJUnitRunner.class)
public class SimpleQueryExecutorTaskletTest {
@InjectMocks
SimpleQueryExecutorTasklet simpleQueryExecutorTasklet;
@Mock
StepContribution stepContribution;
@Mock
ChunkContext chunkContext;
@Mock
JdbcTemplate jdbcTemplate;
@Mock
DataSource dataSource;
String sql="select * from abc;";
@Before
public void setUp() throws Exception {
simpleQueryExecutorTasklet.setDataSource(dataSource);
simpleQueryExecutorTasklet.setSql(sql);
PowerMockito.whenNew(JdbcTemplate.class).withAnyArguments().thenReturn(jdbcTemplate);
}
@Test(expected = NullPointerException.class)
public void testExecute() throws Exception {
simpleQueryExecutorTasklet.execute(stepContribution,chunkContext);
}
@Test
public void testExecute_noException() throws Exception {
Mockito.doNothing().when(jdbcTemplate).execute(Mockito.any(String.class));
simpleQueryExecutorTasklet.execute(stepContribution,chunkContext);
// Here will write some assertions
}
}
Junit 執行的異常日志:
java.lang.NullPointerException
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:390)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:428)
at com.xxxxxx.api.accel.operations.SimpleQueryExecutorTasklet.execute(SimpleQueryExecutorTasklet.java:29)
at com.xxxxxx.api.accel.operations.SimpleQueryExecutorTaskletTest.testExecute_noException(SimpleQueryExecutorTaskletTest.java:61)
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.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)
at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
您使用了錯誤的跑步者。 如果您使用的是 PowerMock,則需要PowerMockRunner
。 此外,當您進入 object 創建時,您需要使用@PrepareForTest
。
@RunWith(PowerMockRunner.class)
@PrepareForTest(JdbcTemplate.class)
public class SimpleQueryExecutorTaskletTest {
...
}
你可以試試下面的代碼
@RunWith(SpringJUnit4ClassRunner.class)
public class DaoImplTests{
@Autowired
private Dao dao;
@Mock
JdbcTemplate jdbcTemplate;
@Test
public void testUsingMockito() {
try {
User mockedUserInfo = new User();
//setters
mockedUserInfo.setXXX;
mockedUserInfo.setYYY;
Mockito.when(((JdbcDaoSupport)dao.getTemplate())).thenReturn(jdbcTemplate);
Mockito.when(jdbcTemplate.queryForObject(Mockito.anyString(), Mockito.any(Object[].class),
Mockito.any(RowMapper.class))).thenReturn(mockedUserInfo);
User userInfo = dao.getUserInfo("");
Assert.assertNotNull(userInfo);
Assert.assertEquals(mockedUserInfo.getXXX(), userInfo.getXXX());
//few more assertions
} catch (Exception e) {
Assert.fail(" : " + e.getMessage());
}
}
}
最后我發現問題出在主要的 class 方法上。 We are creating new JDBC template every time (not injecting) and thats the reason its failing though we are mocking the JDBC template in the junit method. 在更改主 class 代碼以注入 jdbc 模板后,它開始工作。
實際代碼:
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.jdbc.core.JdbcTemplate;
import javax.sql.DataSource;
public class SimpleQueryExecutorTasklet implements Tasklet {
private DataSource dataSource;
private String sql;
private JdbcTemplate jdbcTemplate;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public void setSql(String sql) { this.sql = sql; }
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; }
public JdbcTemplate getJdbcTemplate () {
return this.jdbcTemplate == null ? new JdbcTemplate(dataSource) : this.jdbcTemplate;
}
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
getJdbcTemplate().execute(this.sql);
return RepeatStatus.FINISHED;
}
}
測試代碼:
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.jdbc.core.JdbcTemplate;
import javax.sql.DataSource;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
@RunWith(MockitoJUnitRunner.class)
public class SimpleQueryExecutorTaskletTest {
@InjectMocks
SimpleQueryExecutorTasklet simpleQueryExecutorTasklet;
@Mock
StepContribution stepContribution;
@Mock
ChunkContext chunkContext;
@Mock
JdbcTemplate jdbcTemplate;
@Mock
DataSource dataSource;
String sql="select * from abc;";
@Before
public void setUp() throws Exception {
simpleQueryExecutorTasklet.setDataSource(dataSource);
simpleQueryExecutorTasklet.setSql(sql);
//PowerMockito.whenNew(JdbcTemplate.class).withAnyArguments().thenReturn(jdbcTemplate);
}
@Test
public void testExecute() throws Exception{
simpleQueryExecutorTasklet.setJdbcTemplate(jdbcTemplate);
RepeatStatus repeatStatus = simpleQueryExecutorTasklet.execute(stepContribution,chunkContext);
assertNotNull(repeatStatus);
assertSame("FINISHED", repeatStatus.toString());
}
@Test(expected = NullPointerException.class)
public void testExecute_Exception() throws Exception{
simpleQueryExecutorTasklet.setJdbcTemplate(null);
simpleQueryExecutorTasklet.execute(stepContribution,chunkContext);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.