使用 Mockito 模拟 JPA CriteriaBuilder
我有一个特别令人讨厌的 JPA 查询 JMock check() 块,我想迁移到 Mockito:
Mockery jMock = new Mockery();
final EntityManager fakeEntityManager = jMock.mock(EntityManager.class);
final CriteriaBuilder fakeCriteriaBuilder = jMock.mock(CriteriaBuilder.class);
final CriteriaQuery<String> fakeCriteriaQuery = jMock.mock(CriteriaQuery.class);
jMock.checking(new Expectations() {{
oneOf(fakeEntityManager).getCriteriaBuilder(); will(returnValue(fakeCriteriaBuilder));
oneOf(fakeCriteriaBuilder).createQuery(String.class); will(returnValue(fakeCriteriaQuery));
oneOf(fakeCriteriaQuery).from(Archiveusergrouplicences.class);
oneOf(fakeCriteriaQuery).select(with(any(Selection.class)));
oneOf(fakeCriteriaBuilder).isNotNull(with(any(Expression.class)));
oneOf(fakeCriteriaQuery).where(with(any(Expression.class)));
oneOf(fakeEntityManager).createQuery(fakeCriteriaQuery);
// Return an empty resultset
}});
正在测试的代码如下所示:
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<String> criteria = builder.createQuery(String.class);
Root<Archiveusergrouplicences> institution = criteria.from(Archiveusergrouplicences.class);
criteria.select(institution.get(Archiveusergrouplicences_.usergroupid));
criteria.where(builder.isNotNull(institution.get(Archiveusergrouplicences_.usergroupid)));
List<String> result = entityManager.createQuery(criteria).getResultList();
我发现 这个关于模拟构建器的问题,这在某种程度上解决了模拟的 CriteriaBuilder 部分;但我的主要问题是使用模拟对象作为另一个模拟的 .thenReturn() 值 - Mockito 似乎不允许这样做。例如,对于以下行:
CriteriaQuery<String> criteria = builder.createQuery(String.class);
我想返回模拟 CriteriaQuery 对象,如下所示:
CriteriaQuery<String> fakeCriteriaQuery = mock(CriteriaQuery.class, RETURNS_DEEP_STUBS);
when(entityManager.createQuery(anyString())).thenReturn(fakeCriteriaQuery);
这会引发语法错误:
OngoingStubbing 类型中的方法 thenReturn(Query) 不是 适用于参数 (CriteriaQuery)
我如何测试此代码,或改进它以使其更易于测试?
I have a particularly nasty JMock checking() block for a JPA query that I want to migrate to Mockito:
Mockery jMock = new Mockery();
final EntityManager fakeEntityManager = jMock.mock(EntityManager.class);
final CriteriaBuilder fakeCriteriaBuilder = jMock.mock(CriteriaBuilder.class);
final CriteriaQuery<String> fakeCriteriaQuery = jMock.mock(CriteriaQuery.class);
jMock.checking(new Expectations() {{
oneOf(fakeEntityManager).getCriteriaBuilder(); will(returnValue(fakeCriteriaBuilder));
oneOf(fakeCriteriaBuilder).createQuery(String.class); will(returnValue(fakeCriteriaQuery));
oneOf(fakeCriteriaQuery).from(Archiveusergrouplicences.class);
oneOf(fakeCriteriaQuery).select(with(any(Selection.class)));
oneOf(fakeCriteriaBuilder).isNotNull(with(any(Expression.class)));
oneOf(fakeCriteriaQuery).where(with(any(Expression.class)));
oneOf(fakeEntityManager).createQuery(fakeCriteriaQuery);
// Return an empty resultset
}});
The code being tested looks like this:
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<String> criteria = builder.createQuery(String.class);
Root<Archiveusergrouplicences> institution = criteria.from(Archiveusergrouplicences.class);
criteria.select(institution.get(Archiveusergrouplicences_.usergroupid));
criteria.where(builder.isNotNull(institution.get(Archiveusergrouplicences_.usergroupid)));
List<String> result = entityManager.createQuery(criteria).getResultList();
I've found this question on mocking builders, which goes some way to solving the CriteriaBuilder part of the mock; but my main problem is with using mocked objects as the .thenReturn() value of another mock - Mockito does not seem to allow that. For example, for the line:
CriteriaQuery<String> criteria = builder.createQuery(String.class);
I want to return the mock CriteriaQuery object, like this:
CriteriaQuery<String> fakeCriteriaQuery = mock(CriteriaQuery.class, RETURNS_DEEP_STUBS);
when(entityManager.createQuery(anyString())).thenReturn(fakeCriteriaQuery);
This throws a syntax error:
The method thenReturn(Query) in the type OngoingStubbing is not
applicable for the arguments (CriteriaQuery)
How might I go about testing this code, or improving it to make it more testable?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
事实证明,您可以从其他模拟返回模拟 - 只要您设置正确的参数!我试图断言:
当我真正想要的是通过一个课程时:
错误是 Mockito 以神秘的方式告诉我,我已经搞砸了我的期望。
然而,我可能会考虑重写这个测试,而不是翻译最初编写的内容。正如一些人指出的那样;通常最好避免以这种方式模拟库,并且检查的条件相当模糊。
It turns out you can return mocks from other mocks - so long as you set the right arguments! I was attempting to assert:
When what I actually wanted was to pass in a Class:
The error was Mockito's cryptic way of telling me I had screwed up my expectation.
However, I may look into rewriting this test rather than translating what was originally written. As some have pointed out; it's often better to avoid mocking libraries in this way, and the condition being checked for is rather vague.
就像你 jMock CriteriaQuery
你也需要mockito CriteriaQuery
Like you jMock CriteriaQuery
You need to mockito CriteriaQuery too