0

I have a dataSource bean defined in spring xml as follows

<bean id="apacheBasicDataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close" >
    <property name="url" value="jdbc:oracle:thin:@(DESCRIPTION =(ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521))(CONNECT_DATA =(SERVER = DEDICATED)(SERVICE_NAME = myservice)))" />
    <property name="username" value="${db.username}" />
    <property name="password" value="${db.password}" />
    ...
</bean>

Now I want to test a rest route which do his job by calling stored procedure within a groovy script

<get uri="/utils/foo" produces="text/xml">
    <route id="utils.foo">
        <setBody>
            <groovy>
                import groovy.sql.Sql
                def sql = Sql.newInstance(camelContext.getRegistry().lookupByName('apacheBasicDataSource'))
                res = request.getHeader('invalues').every { invalue ->
                    sql.call("{? = call my_pkg.mapToSomeValue(?)}", [Sql.VARCHAR, invalue]) {
                        outValue -> do some stuff..
                    }
                }
                sql.close()
                new StringBuilder().append(
                    some stuff..
                )
            </groovy>
        </setBody>
    </route>
</get>

I have my test class as follows, so now it works

@SpringBootTest
@RunWith(MockitoJUnitRunner.class)
@ContextConfiguration(locations = {"classpath:camel.xml"})
public class EdiapiApplicationNewTest {

    @Autowired
    private CamelContext context;

    @MockBean private DataSource dataSource;
    @Mock private CallableStatement callableStatement;
    @Mock private Connection connection;
    @Mock private ResultSet resultSet;

    @Test
    public void testSimple() throws Exception {

        when(callableStatement.getResultSet()).thenReturn(resultSet);
        when(dataSource.getConnection()).thenReturn(connection);
        when(connection.prepareCall(anyString())).thenReturn(callableStatement);

        context.getRegistry().bind("apacheBasicDataSource", dataSource);

        TestRestTemplate restTemplate = new TestRestTemplate();
        ResponseEntity<String> response = restTemplate.getForEntity("http://localhost:8080/utils/foo?invalues=foo,bar", String.class);
        Assert.assertEquals("<value>false</value>", response.getBody());
    }
}

But I want to be able to populate mocked ResultSet with some custom value to test against (at the moment it returns null)
I have tried something like

when(resultSet.next()).thenReturn(true).thenReturn(false);
when(resultSet.getString(anyInt())).thenReturn("some value");

With no success. Could someone give me a hint about it? Thanks!

Greenev
  • 871
  • 6
  • 23
  • Can you show your test class? The error above shown when you call the REST API or when the camel context loading? – Esca Tran Sep 24 '20 at 02:20
  • I actually have made a real progress toward the solution, so I've updated the question according to it – Greenev Sep 25 '20 at 21:41
  • The subsequent invocation of nex() does not return false? If that is the issue, then you check the mockito's version. https://www.javadoc.io/doc/org.mockito/mockito-core/2.8.9/org/mockito/Mockito.html#10. Or you can have the internal counter like this example https://stackoverflow.com/questions/8088179/using-mockito-with-multiple-calls-to-the-same-method-with-the-same-arguments – Esca Tran Sep 28 '20 at 01:27
  • @EscaTran Thank you for useful links, however the issue is that the `outValue` in groovy closure always turns to null, even when I have no consecutive sql calls – Greenev Sep 28 '20 at 07:08

1 Answers1

0

Finally I found the roots of the issue as well as a solution.
First, void call method should be mocked with doAnswer and not with thenReturn (obviously).
Second, I dealt with stored function, so there was no getResultSet method invoking on callableStatement, instead the getObject method was invoked, so this is the one should be mocked as

when(callableStatement.getObject(1)).thenAnswer(inv -> "some custom value");
Greenev
  • 871
  • 6
  • 23