I need to create test for this code.
@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;
}
Could you show me how can I mock here getCall.execute(params) response with Mockito?
Your problem here is, that you create the whole getCall object inside your method, which makes it pretty much impossible to somehow inject a mock into that process.
There are a few possibilities here:
a) You can mock your jdbcTemplate and then try to get that to work by mocking all calls that getCall will make to the jdbcTemplate. Since the jdbcTemplate will probably do all the actual db work, this can work, but honestly, it's probably not worth the effort (since it's absolutely non-trivial).
b) You can switch the whole test to an integration-test, letting it run against an in-memory db, for example. Of course, there are many arguments against using an integration test as a substitute for an unit test, so probably this isn't the best way to go, either. It's possible, though, and using the Spring test utils and annotations it can be pretty simple.
c) This leaves us with a bit of work, which in this case means refactoring:
Since your problem is that you create the SimpleJdbcCall internally, one solution would be to to extract that part, for example, into a factory. This simplified example shows that:
@Component
class SimpleJdbcCallFactory {
public SimpleJdbcCall create(JdbcTemplate template) {
return new SimpleJdbcCall(template);
}
}
Now you can add an @Autowired dependency to your class and then mock that depencency in your unit test...
@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);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With