英文:
How to avoid strict stubbing argument mismatch in java
问题
I have an object like
@SuperBuilder(setterPrefix = "set", toBuilder = true)
class Person {
private final String name;
private final boolean active;
}
I use this object in a method like
public SomeType doSomething(Long id) {
Person person = personService.getPersonById(id);
Person updatedPerson = updatePerson(person);
validationService.isValid(updatedPerson);
// ...
}
private Person updatePerson(Person person) {
return person.toBuilder()
.setActive(true)
.build();
}
But when I test this method I get a strict stubbing argument mismatch
void test() {
Person person = Person.builder()
.setName("Name")
.build();
Person updatedPerson = Person.builder()
.setName("Name")
.setActive(true)
.build();
when(personService.getPersonById(1L)).thenReturn(person);
when(validationService.isValid(updatedPerson)).thenReturn(false);
// ...
}
Can someone tell me how to avoid this problem- and create a correct argument?
Thanks for any help!
英文:
I have an object like
@SuperBuilder(setterPrefix = "set", toBuilder = true;
class Person {
private final String name;
private final boolean active;
}
I use this object in a method like
public SomeType doSomething(Long id) {
Person person = personService.getPersonById(id);
Person updatedPerson = updatePerson(person);
validationService.isValid(updatedPerson);
......
}
private Person updatePerson(Person person) {
person.toBuilder()
.setActive(true)
.build();
}
But when I test this method I get a strict stubbing argument mismatch
void test() {
Person person = Person.builder()
.setName("Name")
.build();
Person updatedPerson = Person.builder()
.setName("Name")
.setActive(true)
.build();
when(personService.getPersonById(1L)).thenReturn(person);
when(validationService.isValid(updatedPerson)).thenReturn(false);
.......
Can someone tell me how to avoid this problem- and create a correct argument?
Thanks for any help!
答案1
得分: 0
你有2-3个解决这个问题的选择。最简单的解决方案是简单地覆盖Person
类中的equals
方法(或者只需添加lombok的@EqualsAndHashCode
- 但这将影响您的生产代码(不仅仅是测试本身)。
或者,您可以在这里使用更通用的Mokito匹配器,以下是一些可以工作的示例:
// 仅基于名称/活动字段进行检查
when(validationService.isValid(
ArgumentMatchers.argThat(p -> p.getName().equals("Name")))
)
.thenReturn(true);
// 或者
when(validationService.isValid(Mockito.any(Person.class)))
.thenReturn(true);
// 或者简单地
when(validationService.isValid(Mockito.any()))
.thenReturn(true);
最后,如果validationService不执行任何I/O操作,您可以尝试以不需要模拟它的方式编写代码/测试。换句话说,如果validationService.isValid(p)
只是检查某些状态,也许您可以使用实际对象,并从validationService
决定返回有效或无效的Person
对象。
在我看来,模拟的越少越好...如果可能的话,我个人会尝试最后一种方法。
英文:
You have 2-3 options for solving this issue. The easiest solution would be to simply override the equals
method from the Person
class (or simply add lombok's @EqualsAndHashcode
- but this will affect your production code (not only the test itself).
Alternatively, you can use a more generic Mokito matcher here are some examples that would work:
// check solely based on name/active fields
when(validationService.isValid(
ArgumentMatchers.argThat(p -> p.getName().equals("Name")))
)
.thenReturn(true);
// or
when(validationService.isValid(Mockito.any(Person.class)))
.thenReturn(true);
// or simply
when(validationService.isValid(Mockito.any()))
.thenReturn(true);
Lastly, if validationService is not doing any I/O, you can try to write the code/test in such a way that mocking it is not necessary. In other words, if validationService.isValid(p)
is just checking some state, maybe you can use the actual object and decide from validationService
whether to return a valid or invalid Person
object.
In my opinion, the fewer mocks the better... I would personally try this last approach if possible.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论