如何模拟querydsl查询?

Posted

技术标签:

【中文标题】如何模拟querydsl查询?【英文标题】:How to mock querydsl query? 【发布时间】:2021-11-26 10:35:33 【问题描述】:

在我的产品代码中,我有以下 queryDsl 查询:

Collection<String> myList = new ArrayList<>();
myList.add("blue");
myList.add("green");
myList.add("yellow");

QAnimal qAnimal = QAnimal.animal;
return animalRepository.exists(
        qAnimal.color.in(myList).and(
                qAnimal.name.eq("animal_name")
        )
);

我想使用 Mockito 模拟这个 queryDsl 查询。在我的测试文件中,在我所做的设置方法中:

Collection<Book> myList = new ArrayList<>();
myList.add("blue");
myList.add("green");
myList.add("yellow");

QAnimal qAnimal = QAnimal.animal;

when(qAnimal.color.in(myList)).thenReturn((Expressions.asBoolean(false)));
when(qAnimal.name.eq("animal_name")).thenReturn((Expressions.asBoolean(true)));

运行测试时,我收到以下问题:

org.mockito.exceptions.misusing.MissingMethodInvocationException: 
when() requires an argument which has to be 'a method call on a mock'.
For example:
    when(mock.getArticles()).thenReturn(articles);

Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
   Those methods *cannot* be stubbed/verified.
2. inside when() you don't call method on mock but on some other object.

我无法创建 JPAQuery 对象,只能使用那种查询。

【问题讨论】:

【参考方案1】:

你为什么要嘲笑JPAQuery?此时,您要么测试 Querydsl 的内部结构,要么确保您编写了您所写的内容。只需模拟整个 AnimalRepository 即可。如果您想正确测试animalRepository,最好在实际执行针对数据库的查询的集成测试中这样做。也可以使用querydsl-collections 对模拟数据执行查询。

如果您坚持使用 Mockito 存根模拟 JPAQuery,那么模拟构建器 API(例如 JPAQuery)的最简单方法是使用 Answers.RETURNS_SELF 作为默认存根。

例如,使用以下代码来实例化您的queryMock

@Mock(answer = Answers.RETURNS_SELF) JPAQuery queryMock;

【讨论】:

我想我被误解了。我不想模拟 JPAQuery,我想从第一个 sn-p 模拟 querydsl 代码,我得到了那个错误 qAnimal.color 是静态和字段,Mockito 不能真正模拟静态和字段,主要是方法调用。然而,正因为如此,根本不需要模拟qAnimal.color.in(myList).and(qAnimal.name.eq("animal_name")),而是模拟animalRepository.exists(any()) 但是如果我想为 animalRepository.exists( .. ) 返回不同的案例怎么办?比如有时我想返回false,有时返回true? animalRepository.exists(any()) 总是返回相同的东西(真或假) Mockito.when(mock).thenReturn(a, b, c) 采用多个参数作为返回值,分别用于第一次、第二次、第三次等调用。所以不需要使用不同的参数来从存根返回不同的返回值。 听起来是一个很好的解决方法,但在更改测试的输入时可能会很困难。目前,我会坚持这个解决方案,谢谢!

以上是关于如何模拟querydsl查询?的主要内容,如果未能解决你的问题,请参考以下文章

如何从querydsl获得完全物化的查询

如何使用 QueryDSL 在查询中使用 SAMPLE 关键字

如何在没有域类的 querydsl 中构造查询

为 oneTomany 基于关系的查询编写 queryDSL 谓词查询

如何使用 QueryDsl 在查询中按 id 删除重复行

Querydsl:如何按列进行左连接