【问题标题】:Java Mockito useConstructor withSettings, error Invalid use of argument matchersJava Mockito useConstructor withSettings,错误无效使用参数匹配器
【发布时间】:2021-10-20 18:44:49
【问题描述】:

我正在尝试使用事务管理器模拟以下代码。接收错误如下。我该如何解决这个问题?

代码:

DefaultTransactionDefinition paramTransactionDefinition = new DefaultTransactionDefinition();
PlatformTransactionManager transactionManager = new DataSourceTransactionManager(namedParameterJdbcTemplate.getJdbcTemplate().getDataSource());
TransactionStatus status = transactionManager.getTransaction(paramTransactionDefinition);
  

测试:

@Mock
private JdbcTemplate jdbcTemplate;
@Mock
private PlatformTransactionManager platformTransactionManager;
@Mock
private DataSource dataSource;
@Mock
private TransactionStatus transactionStatus;

given(namedParameterJdbcTemplate.getJdbcTemplate()).willAnswer(a -> jdbcTemplate);
given(namedParameterJdbcTemplate.getJdbcTemplate().getDataSource()).willAnswer(a -> dataSource);
platformTransactionManager = Mockito.mock(DataSourceTransactionManager.class, withSettings().useConstructor(dataSource));

given(platformTransactionManager.getTransaction(any())).willAnswer(a -> transactionStatus);

错误:

org.mockito.exceptions.misusing.InvalidUseOfMatchersException: 
Invalid use of argument matchers!
0 matchers expected, 1 recorded:
-> at         given(platformTransactionManager.getTransaction(any())).willAnswer(a -> transactionStatus);


This exception may occur if matchers are combined with raw values:
    //incorrect:
    someMethod(anyObject(), "raw String");

尝试使用此资源:https://stackoverflow.com/a/60429929/15435022

【问题讨论】:

标签: java spring-boot mockito


【解决方案1】:

我觉得你在嘲讽的时候有点太急切了。 给定应该是这样的:

//method with parameter
given(aMock.aSingleCall(anArgumentMatcher)).willReturn(aValue);
//method without parameter
given(aMock.aSingleCall()).willReturn(aValue);

您在此处使用的链接调用:

given(namedParameterJdbcTemplate.getJdbcTemplate().getDataSource()).willAnswer(a -> dataSource);

应该分成两部分,像这样:

given(namedParameterJdbcTemplate.getJdbcTemplate()).willReturn(jdbcTemplate);
given(jdbcTemplate.getDataSource()).willReturn(dataSource);

在构造函数调用中,您面临着在存根时没有实际使用模拟的问题。 Mockito 将无法用模拟神奇地替换您的构造函数调用(也不应该)。您应该只是使用类似于以下场景之一的东西。

A) 如果您只想模拟 dataSource

以一种可以设置 dataSource 模拟的方式更改您的代码,如下所示:

PlatformTransactionManager transactionManager = new DataSourceTransactionManager(dataSource);

可以通过构造函数或者setter,没关系。

B) 如果你也想模拟transactionManager

更改您的代码以避免直接调用构造函数,接受transactionManager 作为依赖项并设置您已经创建的模拟(名为platformTransactionManager 的字段)。

注意:调用any(aClass)会在any(aClass)被执行时返回类型的默认值。在您的情况下,这是一个 null,因此当您使用它调用真正的构造函数时,您只是在编写 new DataSourceTransactionManager(null) 并带有额外的步骤。

更新#1:如何“以某种方式更改您的代码”?

这取决于您的代码的其余部分,但假设这是在一个方法中:

DefaultTransactionDefinition paramTransactionDefinition = new DefaultTransactionDefinition();
PlatformTransactionManager transactionManager = new DataSourceTransactionManager(namedParameterJdbcTemplate.getJdbcTemplate().getDataSource());
TransactionStatus status = transactionManager.getTransaction(paramTransactionDefinition);

您可以使用PlatformTransactionManager transactionManager 的参数并避免构造函数调用(提取参数),或者您至少可以提取对方法的构造函数调用,并且您可以使用 Mockito 间谍使该方法返回模拟而不是实物。

【讨论】:

【解决方案2】:

这将起作用:

@Mock
private JdbcTemplate jdbcTemplate;
@Mock
private PlatformTransactionManager platformTransactionManager;
@Mock
private DataSource dataSource;
@Mock
private TransactionStatus transactionStatus;

given(namedParameterJdbcTemplate.getJdbcTemplate()).willAnswer(a -> jdbcTemplate);
given(namedParameterJdbcTemplate.getJdbcTemplate().getDataSource()).willAnswer(a -> dataSource);

MockedConstruction<DataSourceTransactionManager> mocked = Mockito.mockConstruction(DataSourceTransactionManager.class,
        (mock, context) -> {
            when(mock.getTransaction(any())).thenReturn(null);
        });
given(platformTransactionManager.getTransaction(new DefaultTransactionDefinition())).willAnswer(a -> transactionStatus);
mocked.close();

资源: https://rieckpil.de/mock-java-constructors-and-their-object-creation-with-mockito/

【讨论】:

    猜你喜欢
    • 2013-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多