Mykhaylo Adamovych
Mykhaylo Adamovych

Reputation: 20956

Mockito. No argument value was captured

How this code should be changed so that it does not throw below exception?

ArgumentCaptor<Date> argument = forClass(Date.class);
verify(ps, times(0)).setDate(anyInt(), argument.capture());

typeHandler.setNonNullParameter(ps, 1, "20170120", DATE);

assertEquals(new Date(2017, 01, 20), argument.getValue());

More code:

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import java.sql.*;

public class DateStringTypeHandler extends BaseTypeHandler<String> {

    private static final DateTimeFormatter YYYY_MM_DD = DateTimeFormat.forPattern("yyyyMMdd");

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
        LocalDate localDate = YYYY_MM_DD.parseLocalDate(parameter);
        ps.setDate(i, new Date(localDate.toDateTimeAtStartOfDay().getMillis()));
    }
}

@RunWith(MockitoJUnitRunner.class)
public class DateStringTypeHandlerTest {

    @Mock
    private PreparedStatement ps;
    private DateStringTypeHandler typeHandler;

    @Before
    public void before() {
        typeHandler = new DateStringTypeHandler();
    }

    @Test
    public void testSetNonNullParameterPreparedStatementIntStringJdbcType() throws SQLException {
        ArgumentCaptor<Date> argument = forClass(Date.class);
        verify(ps, times(0)).setDate(anyInt(), argument.capture());

        typeHandler.setNonNullParameter(ps, 1, "20170120", DATE);

        assertEquals(new Date(2017, 01, 20), argument.getValue());
    }
}      

verify throws exception:

org.mockito.exceptions.base.MockitoException: 
No argument value was captured!
You might have forgotten to use argument.capture() in verify()...
...or you used capture() in stubbing but stubbed method was not called.
Be aware that it is recommended to use capture() only with verify()

Examples of correct argument capturing:
    ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class);
    verify(mock).doSomething(argument.capture());
    assertEquals("John", argument.getValue().getName());

Upvotes: 1

Views: 15940

Answers (2)

Crazy StufF
Crazy StufF

Reputation: 1

I was having the same issue. when I debugged it, the issue turned out that as the debugger goes out of the function, the local scope of the captor declared inside the function diminishes and so I got error.

Try creating/declaring the captor variable inside the class outside of the function. It works!

Upvotes: 0

Maciej Kowalski
Maciej Kowalski

Reputation: 26492

You should invoke the method of the class under test first. Then you verify using the captor:

    @Test
    public void testSetNonNullParameterPreparedStatementIntStringJdbcType() throws SQLException {
        // Arrange
        ArgumentCaptor<Date> argument = forClass(Date.class);

        // Act
        typeHandler.setNonNullParameter(ps, 1, "20170120", DATE);

        // Assert            
        verify(ps).setDate(anyInt(), argument.capture());    
        assertEquals(new Date(2017, 01, 20), argument.getValue());
    }

Also now you probably would not need the times(..) argument.

Upvotes: 4

Related Questions