如何测试SimpleJdbcCall

时间:2017-11-22 08:20:32

标签: mocking mockito jdbctemplate

我需要为此代码创建测试。

@Autowired
JdbcTemplate jdbcTemplate;

public List<Row> getData(int id) {
    // Preconditions here

    SimpleJdbcCall getCall = new SimpleJdbcCall(jdbcTemplate)
            .withSchemaName(SCHEMA)
            .withProcedureName(SP)
            .declareParameters( 
                // ...
            )
            .returningResultSet("result", (RowMapper<QuestionAnswerRow>) (rs, rowNum) -> .....);

    MapSqlParameterSource params = new MapSqlParameterSource();
    params.addValue("id", id);
    // other parameters here

    Map queryRes = getCall.execute(params);
    List<row> res = (List<row>) queryRes.get("result");
    return res;
}

你能否告诉我如何在这里模仿getCall.execute(params)对Mockito的反应?

2 个答案:

答案 0 :(得分:2)

你的问题是,你在方法中创建了整个getCall对象,这使得以某种方式将模拟注入到该进程中几乎是不可能的。

这里有一些可能性:

a)您可以模拟jdbcTemplate,然后通过模拟getCall将对jdbcTemplate发出的所有来电来尝试使其发挥作用。由于jdbcTemplate可能会完成所有实际的数据库工作,所以这可以工作,但老实说,它可能不值得努力(因为它绝对不重要)。

b)例如,您可以将整个测试切换到集成测试,让它针对内存中的数据库运行。当然,有许多反对使用集成测试作为单元测试的替代品的论据,所以这可能不是最好的方法。但是,有可能使用Spring测试工具和注释它可以非常简单。

c)这给我们留下了一些工作,在这种情况下意味着重构:

由于您的问题是您在内部创建SimpleJdbcCall,因此一种解决方案是将该部分(例如)提取到工厂中。这个简化的例子表明:

@Component
class SimpleJdbcCallFactory {
   public SimpleJdbcCall create(JdbcTemplate template) {
       return new SimpleJdbcCall(template);
   }
}

现在你可以在你的班级中添加一个@Autowired依赖项,然后在单元测试中模拟这种依赖性......

@RunWith(MockitoJUnitRunner.class)
public class YourTestClassHere {

   @Mock
   private SimpleJdbcCallFactory simpleJdbcCallFactory;

   @InjectMocks
   private YourClassHere classToTest;

   @Test
   public void test() {
        SimpleJdbcCall mockedCall = Mockito.mock(SimpleJdbcCall.class);
        Mockito.when( simpleJdbcCallFactory.create(Mockito.any())).thenReturn(mockedCall);
        Mockito.when( mockedCall ).withSchemaName(Mockito.anyString()).thenReturn(mockedCall);
        // etc. unfortunately needed for fluent apis (unless they added those in mockito)
        Mockito.when( mockedCall.execute(Mockito.any()).thenReturn( ... );

        classToTest.getData(123);
   }

}

答案 1 :(得分:0)

要解决no datasource specified,我们需要模拟SimpleJdbcCall,上面的代码正在调用原始方法。所以我们遇到了错误。

请使用Power Mockito模拟如下所示的参数化构造函数

JdbcTemplate jdbcTemplateMock = Mockito.mock(JdbcTemplate.class);
SimpleJdbcCall mockedSimpleJdbcCall = Mockito.mock(SimpleJdbcCall.class);

PowerMockito.whenNew(SimpleJdbcCall.class).withArguments(jdbcTemplateMock).thenReturn(mockedSimpleJdbcCall);