如何测试SimpleJDBCall

tkqqtvp1  于 2021-07-03  发布在  Java
关注(0)|答案(2)|浏览(362)

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

@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的回应?

idv4meu8

idv4meu81#

解决 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);
jexiocij

jexiocij2#

你的问题是,你创造了整个世界 getCall 对象,这使得几乎不可能以某种方式向该进程中注入模拟。
这里有一些可能性:
a) 你可以嘲笑你的朋友 jdbcTemplate 然后试着通过嘲笑所有的电话来让它工作 getCall 将使 jdbcTemplate . 自从 jdbcTemplate 可能会做所有实际的数据库工作,这可以工作,但老实说,这可能不值得的努力(因为它是绝对不平凡的)。
b) 例如,您可以将整个测试切换到集成测试,让它在内存db上运行。当然,有很多反对使用集成测试来代替单元测试的观点,所以这也可能不是最好的方法。不过,这是可能的,而且使用spring测试utils和注解可以非常简单。
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);
   }

}

相关问题