当前位置: 首页 > 知识库问答 >
问题:

Mockito ErrorTypeOfReturnValue:findById()无法返回布尔值

公冶鸣
2023-03-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())

尽管我已经嘲笑了这个.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()应该返回可选的***如果您不确定为什么会出现上述错误,请继续阅读。由于上述语法的性质,可能会出现问题,因为:

    < li >此异常可能发生在错误编写的多线程测试中。请参考Mockito关于并发测试限制的FAQ。 < li >使用when(spy.foo())清除间谍。then()语法。干掉间谍更安全- < ul > < li >使用doReturn|Throw()方法系列。更多信息请参见javadocs for Mockito.spy()方法。

我还尝试了以下变体:

Mockito.doReturn(true).when(this.petRepository.findById(0)).isPresent();

但我得到了以下例外:

org.mockito.exceptions.misusing.UnfinishedStubbingException: Unfinish stubbing 检测到此处: -

E、 g.thenReturn()可能丢失。正确的存根示例:when(mock.isOk())。然后返回(true);当(mock.isOk())。然后抛出(异常);doThrow(异常)。when(模拟)。someVoidMethod();提示:

  1. missing thenReturn()
  2. 您正在尝试存根最终方法,该方法不受支持
  3. 在“然后返回”指令完成之前,您正在内脏添加另一个模拟的行为

对如何解决这个问题有什么想法吗?

共有1个答案

姜磊
2023-03-14

在<code>init返回一个非模拟可选项,这很好。在新的测试中,您试图为<code>isPresent</code>设置返回值,但您不能这样做,因为Optional不是mock。如果要重写每个测试的行为,则需要stub<code>findById

Mockito.when(this.petRepository.findById(0))
    .thenReturn(java.util.Optional.of(pet));

Mockito的工作原理是创建一个模拟对象,该对象子类化一个类并覆盖每个方法。重写的方法与静态 (ThreadLocal) 基础结构交互,允许您使用 when 语法。这里重要的是,当忽略它的论点,而是试图嘲笑你用一个模拟进行的最后一次互动。您可以在 SO 问题中找到更多信息 mockito when() invocation 如何工作?和Mockito匹配器如何工作?

当您看到此呼叫时:

Mockito.when(this.petRepository.findById(0))
    .thenReturn(java.util.Optional.of(pet));

然后它按您的预期工作:

  1. petRepository是一个mock,findById大概是一个可重写的方法,Mockito记录了您用参数<code>0
  2. <code>findById</code>还没有任何被截留的行为,因此它执行其默认值,返回<code>null</code>
  3. <code>当</code>不关心它刚刚收到<code>null</code>时,因为<code>null</code>没有告诉它调用了什么方法来获得<code>空</编码>的任何信息。相反,它会查看其最近的记录(findById(0)),并返回一个对象,其中包含您期望的thenVerb方法
  4. 调用<code>然后返回,因此Mockito设置<code>petRepository

但是当你尝试这个电话:

Mockito.when(this.petRepository.findById(0).isPresent()).thenReturn(true);

那么最近的交互不是< code>isPresent,而是< code>findById,所以Mockito假设您希望< code > find byid(0) to < code > then return(true)并抛出WrongTypeOfReturnValue。Optional不是mock,所以与它交互不会让Mockito记录它的交互或者重放你的行为。值得一提的是,我也不建议模仿它:Optional是一个final类,尽管Mockito最近添加了一些对模仿final类型的支持,但Optional足够简单和直接,因此只返回您想要的可选实例比试图模仿它更有意义。

尽管如此,您的html" target="_blank">代码看起来是正确的;只要PetRepository是一个接口,我就看不到任何关于方法外观或模拟外观的东西会导致<code>this.PetRepository。findById(0)返回缺席的可选项。事实上,我甚至不知道你会在哪里创建一个缺席的可选项,让它返回,所以我只能猜测你在测试中使用的真实对象比你想象的要多。

 类似资料:
  • 这是一个布尔方法,是我作业的一小部分。我想根据输入和记录之间是否匹配来返回true或false。我想我遇到了语法问题。 这是该方法的代码,但始终有红线指示我应该在代码中添加return,否则将该方法更改为void。但我已经在if语句中添加了return true。

  • 好的,我的问题是关于布尔返回。对于我的Comp-Sci作业,我必须使用多种方法制作一个课程注册程序,其中之一就是添加课程方法。基本上,在目录中搜索类,如果匹配,则将其添加到学生计划中,并返回布尔值true。我这么做了,但出于某种原因,这给了我一个错误。以下是代码: 为什么它不能识别布尔返回值?是因为我把它们放在了一个圈里吗?

  • 问题内容: 关于以下原因为何的任何想法。 当我将request_url粘贴到浏览器中时,我会获取json数据,但是如果我在php中尝试,则var_dump就是bool(false); 有任何想法吗?? 更新并修复 OK伙计们,感谢您的所有帮助。是的,我帮助我追踪了这一情况。事实证明,php.ini配置为禁止打开url,因此file_get_contents无法正常工作。我在各个站点上发现了以下方便

  • 是否可以编写如下JPQL查询: <代码>选择计数(*) 这将根据实体填充条件是否存在返回真/假布尔值? 我想这样使用查询: 我示例中的查询在语法上不正确(解析错误),但是是否有任何正确的方法可以像在JPQL中那样进行检查,从而返回布尔值,或者只有在Java代码中才有可能?

  • 问题内容: 我喜欢用其他语言在方法/函数名称的末尾使用问号。Java不允许我这样做。作为一种解决方法,我还能如何用Java命名布尔返回方法?使用,,,在好一些情况下,方法声音的前端。是否有更好的方法来命名此类方法? 例如,createFreshSnapshot? 问题答案: 惯例是用名字问一个问题。 以下是在JDK中可以找到的一些示例: 这样,名称的读取方式就像它们的末尾带有问号一样。 收藏集是否

  • 问题内容: 我有一些EditText,用户可以输入ftp地址,用户名,密码,端口和testConnection按钮。如果成功建立连接,它将返回布尔值true。 我正在重新编写代码以使用AsyncTasks执行各种ftp操作,但是,如果连接成功,如何传递布尔值? 还有我的AsyncTask 问题答案: 如果myMethod从onPostExecute内部代码调用,它将在UI线程上运行。否则,你需要通