【问题标题】:Mocking DynamoDB mapper query using Mockito使用 Mockito 模拟 DynamoDB 映射器查询
【发布时间】:2022-01-27 21:38:46
【问题描述】:

我正在尝试模拟一个非常简单的代码行,该代码行用于使用 Java 查询 DynamoDB。这是查询的一些示例代码 -

List<Pojo> result;
        try {
            if (filters == null) {
                this.queryExpression = new DynamoDBQueryExpression<Pojo>()
                        .withKeyConditionExpression(partitionKeyCondition)
                        .withExpressionAttributeValues(this.eav);
            } else {
                setFilterQueryExpression(filters);
            }
            result = this.dynamoDBMapper.query(Pojo.class, queryExpression);
        } catch (final Exception e) {
            throw new InternalServerException("Something went wrong with the database query: ", e);
        }

上面的代码有效,我可以检索自动反序列化到 Pojo 中的行列表。

我现在正尝试按如下方式模拟 this.dynamoDBMapper.query 调用 -

@Mock
private DynamoDBMapper mapper;
List<Pojo> result = new ArrayList<>();

when(mapper.query(Pojo.class,Mockito.any(DynamoDBQueryExpression.class)).thenReturn(result);

我无法做到这一点,但出现错误 -

Cannot resolve method 'thenReturn(java.util.List<com.amazon.xxx.xxx.Pojo>)'

我也尝试了另一种方法-

doReturn(result).when(mapper).query(Pojo.class, Mockito.any(DynamoDBQueryExpression.class));

这似乎可以编译,但测试失败并出现错误 -

org.mockito.exceptions.misusing.WrongTypeOfReturnValue 

我查看了查询的预期输出类型为 PaginatedQueryList 的其他示例,我也尝试更改为该示例。但是我仍然不确定为什么上面会抛出错误。

【问题讨论】:

  • 您是否尝试过将 List 更改为 PaginatedQueryList 或类似的?根据文档,查询方法返回 List 的特定实现。您可以将特定实现分配给更通用的 List 变量,但不能返回更通用的类型,其中每个签名都请求特定实现。因此,Mockito 无法解析您要求的方法。
  • 我确实尝试将返回类型从List 更改为PaginatedQueryList,但when 仍然不接受它。它说Cannot resolve method 'thenReturn(PaginatedQueryList&lt;Pojo&gt;)'。我觉得我需要做一些额外的事情才能让它发挥作用,但我不完全确定如何。

标签: java amazon-web-services mockito amazon-dynamodb dynamodb-mapper


【解决方案1】:

您在使用 ArgumentMatchers 时是否也遇到错误?

Mockito.when(mapper.query(ArgumentMatchers.any(Pojo.class),ArgumentMatchers.any(DynamoDBQueryExpression.class)).thenReturn(result));

如果您(临时)展开 ArgumentMatchers,您是否也会收到错误消息?

Mockito.when(mapper.query(ArgumentMatchers.any(),ArgumentMatchers.any()).thenReturn(result));

【讨论】:

  • 是的,它不会改变任何东西。我已经尝试用any() 替换参数。
  • @Samarth 你能进入 .query() 方法并检查返回类型吗?它是 List 还是基类? WrongTypeOfReturnValue 和无法解析方法 List<...pojo> 以某种方式暗示返回值为 false。还要检查返回值是否类似于 List extends something> 因为你的 Pojo 也需要扩展“something”。
  • 返回类型为PaginatedQueryList,如文档中所述。我尝试将代码中的所有返回类型从List 切换到PaginatedQueryList,但我仍然遇到错误。有关更多信息,请参阅问题评论。
【解决方案2】:

事实证明,您在 .thenReturn 之前缺少一个括号,以便完成 when 部分。一旦你添加它并从返回类型List 切换到PaginatedQueryList,它应该可以编译。另请注意,any 是一个匹配器。一旦你指定了一个匹配器,所有的参数都需要是匹配器,因此使用eq 等作为你的 Pojo 类型。否则,Mockito 将在运行时显示InvalidUseOfMatchersException。这是一个适用于我的简化示例:

import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBQueryExpression;
import com.amazonaws.services.dynamodbv2.datamodeling.PaginatedQueryList;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class MockTest {

    @Test
    void test() {
        DynamoDBMapper mapperMock = mock(DynamoDBMapper.class);
        PaginatedQueryList<String> expected = mock(PaginatedQueryList.class);
        // Note that when needs to be completed before thenReturn can be called.
        when(mapperMock.query(eq(String.class), Mockito.any(DynamoDBQueryExpression.class))).thenReturn(expected);

        QueryService queryService = new QueryService(mapperMock);
        PaginatedQueryList<String> actual = queryService.query();

        assertEquals(expected, actual);
    }

    public class QueryService {
        private final DynamoDBMapper mapper;

        public QueryService(DynamoDBMapper mapper) {
            this.mapper = mapper;
        }

        public PaginatedQueryList<String> query() {
            DynamoDBQueryExpression<String> queryExpression = new DynamoDBQueryExpression<>();
            return mapper.query(String.class, queryExpression);
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-20
    • 2019-05-03
    • 1970-01-01
    • 1970-01-01
    • 2019-07-13
    • 1970-01-01
    相关资源
    最近更新 更多