Mockito定义'何时'调用答案

时间:2014-06-17 11:32:14

标签: java unit-testing junit mockito

我需要模拟JDBC更新语句,并且我想确保发送的更新字符串是正确的。我有一个MockConnectionManager,它定义了以下定义预期查询字符串的方法:

public void setUpdateExpectedQuery(String ...expectedQueryStrings) throws SQLException {

    Statement mockStatement = mock(Statement.class);
    when(mockConnection.createStatement()).thenReturn(mockStatement);

    when(mockStatement.executeUpdate(anyString())).then(new Answer<String>() {

        @Override
        public String answer(InvocationOnMock invocationOnMock) throws Throwable {
            String str = Arrays.toString(invocationOnMock.getArguments());
            throw new RuntimeException("Update string is not as expected: " + str);
        }

    });

    for(String expected : expectedQueryStrings) {
        when(mockStatement.executeUpdate(expected)).then(new Answer<Void>() {

            @Override
            public Void answer(InvocationOnMock invocationOnMock) throws Throwable {
                // Do something, just don't throw an exception here.
                return null;
            }

        });
    }
}

我希望如果遇到意外的查询字符串,则会抛出异常。我们期望的查询字符串如Mockito wiki(http://docs.mockito.googlecode.com/hg/latest/org/mockito/Mockito.html#2)中所述。

出于某种原因,在执行测试并只调用setUpdateExpectedQuery时,会抛出异常。

MockConnectionManager connectionManager = (MockConnectionManager) context.getBean("connectionManager");

connectionManager.setUpdateExpectedQuery("INSERT WHATEVER INTO WHENEVER");

与第一个答案中写的相同的异常:java.lang.RuntimeException:更新字符串不符合预期:[INSERT WHATEVER INTO WHENEVER]

这怎么可能?正在调用'何时'实际调用该方法?我从来没有在其他情况下看到它......

1 个答案:

答案 0 :(得分:2)

我怀疑问题是你在循环中的调用(当你调用mockStatement.executeUpdate(expected)时)与先前的when(mockStatement.executeUpdate(anyString()))模拟匹配。

请记住,模拟知道您在when中调用的内容的方式是因为您正在调用它 - 想象将when(mockStatement.executeUpdate(anyString()))翻译成:

int result = mockStatement.executeUpdate(anyString());
OngoingStubbing<Integer> tmp = when(result);
tmp.then(...);

您可能只需要进行 when(...)来电。所以:

public void setUpdateExpectedQuery(String ...expectedQueryStrings)
    throws SQLException {
    final Set<String> capturedQueries = new HashSet<>
       (Arrays.asList(expectedQueryStrings);

    Statement mockStatement = mock(Statement.class);
    when(mockConnection.createStatement()).thenReturn(mockStatement);

    when(mockStatement.executeUpdate(anyString())).then(new Answer<String>() {    
        @Override
        public String answer(InvocationOnMock invocationOnMock) throws Throwable {
            String query = (String) invocationOnMock.getArguments[0];
            if (capturedQueries.contains(query)) {
                return null;
            }
            throw new RuntimeException("Update string is not as expected: " + query);
        }

    });
}