简体   繁体   中英

How to Mock Spring JDBCTemplate execute method in Junit Test case

When I am executing the second test testExecute_noException, still its returning null pointer exception. For first test is returning null pointer exception is valid, but for the second test I need to continue with the next lines tests. Please refer more details in below.


Actual Code:

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;
    }
}

Test Code:

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
    }
}

Exception log from Junit execution:

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)

You are using the wrong runner. If you are using PowerMock, you need PowerMockRunner . Also, you need to use @PrepareForTest when you tap into object creation.

@RunWith(PowerMockRunner.class)
@PrepareForTest(JdbcTemplate.class)
public class SimpleQueryExecutorTaskletTest {
...
}

You can try below code

@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());
        }
    }

}

Finally I found that the issue is with the main class method. 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. After the changing main class the code to inject the jdbc template, it started working.

Actual Code:

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;
    }
}

Test code:

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);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM