【发布时间】:2022-01-31 12:56:14
【问题描述】:
我正在尝试使用 Mockito 通过 JUnit 测试来测试以下方法:
@Override public List<Adoption> search(String username, Integer id) {
List<Adoption> emptySearchResult = new ArrayList<>();
if(id != null && !username.equals("") ) {
if(!this.petRepository.findById(id).isPresent()){
return emptySearchResult;
}
if(!this.appUserRepository.findByUsername(username).isPresent()){
return emptySearchResult;
}
Pet pet = this.petRepository.findById(id).orElseThrow( () -> new PetNotFoundException(id));
AppUser user = this.appUserRepository.findByUsername(username).orElseThrow( () -> new UsernameNotFoundException(username));
return this.adoptionRepository.findAllByUserAndPet(user, pet);
}
else if(id != null && username.equals("")){
if(!this.petRepository.findById(id).isPresent()){
return emptySearchResult;
}
Pet pet = this.petRepository.findById(id).orElseThrow( () -> new PetNotFoundException(id));
return this.adoptionRepository.findAllByPet(pet);
}
else if(id == null && !username.equals("")) {
if(!this.appUserRepository.findByUsername(username).isPresent()){
return emptySearchResult;
}
AppUser user = this.appUserRepository.findByUsername(username).orElseThrow( () -> new UsernameNotFoundException(username));
return this.adoptionRepository.findAllByUser(user);
}
else {
return this.adoptionRepository.findAll();
}
}
但是,我在以下部分遇到了问题:
if(!this.petRepository.findById(id).isPresent())
尽管我已经模拟了 this.petRepository.findById(id),但由于某种原因 isPresent() 返回 false。这是我对测试的初始化:
@Mock
private AdoptionRepository adoptionRepository;
@Mock
private PetRepository petRepository;
@Mock
private AppUserRepository appUserRepository;
private AdoptionServiceImpl service;
private Adoption adoption1;
private Adoption adoption2;
private Adoption adoption3;
private AppUser user;
private AppUser user2;
private Pet pet;
private Pet petAlteadyAdopted;
List<Adoption> allAdoptions = new ArrayList<>();
List<Adoption> userFilteredAdoptions = new ArrayList<>();
List<Adoption> petFilteredAdoptions = new ArrayList<>();
@Before
public void init() {
MockitoAnnotations.initMocks(this);
user = new AppUser("username","name","lastname","email@gmail.com","pass",ZonedDateTime.now(), Role.ROLE_USER, City.Skopje);
user2 = new AppUser("username1","name","lastname","email@gmail.com","pass",ZonedDateTime.now(), Role.ROLE_USER, City.Skopje);
Center center = new Center("a", City.Bitola,"url");
pet = new Pet("p", Type.DOG,"b", Gender.FEMALE,"d",center, ZonedDateTime.now(),"url",null,false,ZonedDateTime.now());
petAlteadyAdopted = new Pet("p", Type.DOG,"b", Gender.FEMALE,"d",center, ZonedDateTime.now(),"url",null,true,ZonedDateTime.now());
pet.setId(0);
petAlteadyAdopted.setId(1);
adoption1 = new Adoption(ZonedDateTime.now(),ZonedDateTime.now(),Status.ACTIVE,user,pet);
adoption2 = new Adoption(ZonedDateTime.now(),ZonedDateTime.now(),Status.CLOSED,user,pet);
adoption3 = new Adoption(ZonedDateTime.now(),ZonedDateTime.now(),Status.CLOSED,user2,new Pet());
allAdoptions.add(adoption1);
allAdoptions.add(adoption2);
allAdoptions.add(adoption3);
petFilteredAdoptions.add(adoption2);
petFilteredAdoptions.add(adoption1);
userFilteredAdoptions.add(adoption2);
userFilteredAdoptions.add(adoption1);
Mockito.when(this.adoptionRepository.findById(0)).thenReturn(java.util.Optional.of(adoption1));
Mockito.when(this.adoptionRepository.findById(1)).thenReturn(java.util.Optional.of(adoption2));
Mockito.when(this.petRepository.findById(0)).thenReturn(java.util.Optional.of(pet));
Mockito.when(this.petRepository.findById(1)).thenReturn(java.util.Optional.of(petAlteadyAdopted));
Mockito.when(this.appUserRepository.findByUsername("username")).thenReturn(java.util.Optional.of(user));
Mockito.when(this.appUserRepository.findByUsername("username1")).thenReturn(java.util.Optional.of(user2));
Mockito.when(this.adoptionRepository.findAll()).thenReturn(allAdoptions);
Mockito.when(this.adoptionRepository.findAllByPet(pet)).thenReturn(petFilteredAdoptions);
Mockito.when(this.adoptionRepository.findAllByUser(user)).thenReturn(userFilteredAdoptions);
Mockito.when(this.adoptionRepository.findAllByUserAndPet(user,pet)).thenReturn(userFilteredAdoptions);
Mockito.when(this.adoptionRepository.save(Mockito.any(Adoption.class))).thenReturn(adoption1);
this.service = Mockito.spy(new AdoptionServiceImpl(this.adoptionRepository, this.petRepository,this.appUserRepository));
}
因此,以下测试失败,即使它应该通过:
@Test
public void searchTest2() {
List<Adoption> adoptionList = this.service.search("",0);
Assert.assertEquals(petFilteredAdoptions,adoptionList);
}
为了解决这个问题,我尝试模拟 isPresent() 方法:
Mockito.when(this.petRepository.findById(0).isPresent()).thenReturn(true);
但我得到以下异常:
org.mockito.exceptions.misusing.WrongTypeOfReturnValue: findById() 不能返回布尔值 findById() 应该返回 可选的*** 如果您不确定为什么会出现上述错误,请继续阅读。因为 可能会出现上述语法问题的性质,因为:
- 此异常可能发生在错误编写的多线程测试中。请参阅 Mockito 常见问题解答以了解并发限制 测试。
- 使用 when(spy.foo()).then() 语法对间谍进行存根。存根间谍更安全-
- 使用 doReturn|Throw() 系列方法。更多关于 Mockito.spy() 方法的 javadocs。
我还尝试了以下变体:
Mockito.doReturn(true).when(this.petRepository.findById(0)).isPresent();
但后来我得到了以下异常:
org.mockito.exceptions.misusing.UnfinishedStubbingException: 此处检测到未完成的存根: -> 在 mk.finki.ukim.milenichinja.ServiceTests.AdoptionServiceFilterTests.init(AdoptionServiceFilterTests.java:87)
例如thenReturn() 可能会丢失。正确的存根示例: 当(模拟。isOk())。然后返回(真); when(mock.isOk()).thenThrow(异常); doThrow(exception).when(mock).someVoidMethod();提示:
- 缺少 thenReturn()
- 您正在尝试存根不支持的最终方法
- 在“thenReturn”指令完成之前,您正在对内部另一个模拟的行为进行存根
任何想法如何解决这个问题?
【问题讨论】:
-
感谢您如此清晰地显示您的代码。第二条错误消息中的第 87 行是哪一行?哪一行给出了 WrongTypeOfReturnValue 错误?
-
@JeffBowman 是这一行:Mockito.doReturn(true).when(this.petRepository.findById(0)).isPresent();
标签: java spring unit-testing mockito boolean