【问题标题】:How to get values from the @autowired field in a class to test and how to get value from abstract method如何从类中的@autowired 字段中获取值以进行测试以及如何从抽象方法中获取值
【发布时间】:2017-11-29 02:45:52
【问题描述】:

我正在使用 Mockito 使用 Junit 测试我的 java 类。 我是 Mockito 和 Junit 测试用例的新手。 我有一堂有弹簧配置的课。 请看下面的代码sn-p。

 public abstract class AbstractTaskDao implements TaskDao {
        @Autowired
        NamedParameterJdbcTemplate jdbcTemplate;

        @Override
        public void addTask(BlockingQueue<String> queue, LocalDate tdate) {
            String sql = getQuery();
            Map<String, Object> paramMap = new HashMap<>();
            paramMap.put("tdate", Date.valueOf(tdate));


            ((JdbcTemplate) jdbcTemplate.getJdbcOperations()).setFetchSize(1000);
            jdbcTemplate.query(sql, paramMap,new classA());
        }
        protected abstract String getQuery();
    }

    Below is my test class.

    public class AbstractTaskDaoTest { 
        @Mock NamedParameterJdbcTemplate jdbcTemplate; 
        @Mock JdbcOperations operation;
        BlockingQueue<String> myqueue;
        @Before
         public void setUp() throws IOException {   
           jdbcTemplate=mock(NamedParameterJdbcTemplate.class);         
                when(jdbcTemplate.getJdbcOperations()).thenReturn(operation);       
              //use reflection to inject autowired field.       
       org.springframework.test.util.ReflectionTestUtils.setField(abstratTaskPDao, "jdbcTemplate", jdbcTemplate);

                        }

                    @Test
                    public void testTask() throws InterruptedException{
                        LocalDate tdate=LocalDate.parse("2014-02-23");
                        AbstractTaskDao  abstratTaskDao = Mockito.mock(AbstractTaskDao .class, Mockito.CALLS_REAL_METHODS);
                        System.out.println("\n\t sql-"+abstratTaskDao.getQuery());
                        abstratTaskDao.addTask(myqueue,tdate);
                    }
                }

以上测试用例在“((JdbcTemplate) jdbcTemplate.getJdbcOperations()).setFetchSize(1000);”行抛出NullPointerException

所以在上面的代码中,我将 getQuery 设为 null。因为它由其他类实现,如 MyclassQuery 类扩展 AbstractTaskDao 包含方法 getQuery() 的实现。 但我是 Mockito 和 Junit 测试用例世界的新手,所以我不知道如何在测试中进行显式调用。

第二件事是这里的@Autowired 字段,它是 jdbcTemplate 正在为空。那么我将如何获得它的值。

更新: 我收到代码“((JdbcTemplate)jdbcTemplate.getJdbcOperations()).setFetchSize(1000);”的类转换异常由于 jdbcTemplate 是 NamedParameterJdbcTemplate。如何解决这个问题。

To solve this issue I added below line to code in AbstractTaskDaoTest class.
 @Mock JdbcTemplate jdbcTemp;
 jdbcTemp=mock(JdbcTemplate.class);         
 when(jdbcTemplate.getJdbcOperations()).thenReturn(jdbcTemp);     

【问题讨论】:

  • 1) 模拟jdbcTemplate 2) 使用@injectMocks 注解注入你的依赖。这两件事是 mokito 的常见做法。
  • 模拟抽象方法和指定标志Mockito.CALLS_REAL_METHODS 的组合我猜应该不起作用。您可能想要模拟该方法或为实现该方法的子类之一创建一个 Mock。
  • @MinhKieu 我添加了@InjectMocks NamedParameterJdbcTemplate jdbcTemplate;像这样,但它仍然给出空值。即使我在这里获得了这个模板的值,我如何将这个值传递给我想要测试的类?
  • 抱歉没有更清楚。我假设你知道我在说什么:)。好的,所以你@Mock NamedParameterJdbcTemplate jdbcTemplate。显然这只是一个模拟,所以你需要告诉 Mockito 你希望它如何工作。例如JdbcOperations operation = Mock(JdbcOperations.class);when(jdbcTemplate.getJdbcOperations()).thenReturn(operation);。希望这能让它更清楚。
  • @MinhKieu 感谢让它更清晰,当我尝试添加这一行 jdbcTemplate.getJdbcOperations() 作为 jdbcTemplate 提供空对象时,它会在我尝试在其空对象中设置操作时提供空指针。

标签: java spring-mvc junit mockito testcase


【解决方案1】:

试试这段代码,我还没有完全编译,所以你需要弄清楚最后一行。

@Test
public void testTask() throws InterruptedException {
    //arrange
    LocalDate tdate = LocalDate.parse("2014-02-23");
    AbstractTaskDao abstratTaskDao = Mockito.mock(AbstractTaskDao.class, Mockito.CALLS_REAL_METHODS);
    NamedParameterJdbcTemplate jdbcTemplate = Mockito.mock(NamedParameterJdbcTemplate.class);
    JdbcOperations operations =  Mockito.mock(JdbcOperations.class);

    when(jdbcTemplate.getJdbcOperations()).thenReturn(operations);
    when(abstratTaskDao.getQuery()).thenReturn("select * from dual");

    //use reflection to inject autowired field.
    org.springframework.test.util.ReflectionTestUtils.setField(abstratTaskDao, "jdbcTemplate", jdbcTemplate);

    System.out.println("\n\t sql-"+abstratTaskDao.getQuery());

    //act
    abstratTaskDao.addTask(myqueue, tdate);

    //assert
    verify(jdbcTemplate).query(...);

}

【讨论】:

  • 我收到此错误“需要但未调用:实际上,与此模拟的交互为零。”在行 verify().queryForList()
  • 更新您的问题并发布您的新测试代码。基本上,它是说您验证某个方法调用执行一次,但从未调用过。
  • 我已经更新了它,问题现在作为(JdbcTemplate)的类转换异常给出。因为我正在传递 NamedJdbcparameterTemplate 对象。
  • 错误:org.springframework.jdbc.core.JdbcOperations$$EnhancerByMockitoWithCGLIB$$ba144ce6 无法转换为 org.springframework.jdbc.core.JdbcTemplate
  • jdbcTemplate.getJdbcOperations() 根据文档返回 JdbcOperations。所以我猜你选错了类型?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多