Как смоделировать метод выполнения Spring JDBCTemplate в тестовом примере Junit - PullRequest
1 голос
/ 23 октября 2019

Когда я выполняю второй тест testExecute_noException, все равно возвращается исключение нулевого указателя. Для первого теста возвращается нулевой указатель, исключение допустимо, но для второго теста мне нужно продолжить следующие тесты строк. Подробнее см. Ниже.


Фактический код:

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)

Ответы [ 3 ]

0 голосов
/ 23 октября 2019

Вы можете попробовать ниже код

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

}
0 голосов
/ 28 октября 2019

Наконец я обнаружил, что проблема связана с методом основного класса. Мы создаем новый шаблон JDBC каждый раз (не для инъекций), и в этом причина его неудачи, хотя мы высмеиваем шаблон JDBC в методе junit. После изменения основного класса кода для внедрения шаблона 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);
    }
}
0 голосов
/ 23 октября 2019

Вы используете не того бегуна. Если вы используете PowerMock, вам нужно PowerMockRunner. Кроме того, вам нужно использовать @PrepareForTest при нажатии на создание объекта.

@RunWith(PowerMockRunner.class)
@PrepareForTest(JdbcTemplate.class)
public class SimpleQueryExecutorTaskletTest {
...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...