使用Mockito调用实数方法

lsmd5eda  于 2022-11-08  发布在  其他
关注(0)|答案(3)|浏览(162)

我正在使用JDK 11和spring boot。我正在实现一个rest API,有3层:

  • 控制器
  • 服务层
  • 数据访问层

我在数据访问层有针对接口的类,而在服务层没有任何接口。
我使用MockMvc、Mockito等编写了集成测试,以测试控制器所公开的每个点的整个路径。
最初,我只模拟了仓库/Daos。所以类结构看起来像:

public interface ClientRepo{
    ......
    }

    public class ClientRepoImpl implements ClientRepo{
    ......
    }

将返回的数据模拟为:

@MockBean 
    private ClientRepo client;

    ....
    Mockito.when(client.isExistFkUnitId(Mockito.any(UUID.class))).thenReturn(false);

到目前为止一切都很好。
现在我已经在服务层引入了接口:

public interface ClientService{
    ......
    }

    public class ClientServiceImpl implements ClientService{
    ......
    }

并尝试了**(尝试调用实际服务方法)**:

@MockBean 
    private ClientService clientService;

    ....
    Mockito.when(clientService.isExistFkUnitId(Mockito.any())).thenCallRealMethod();

却总是空无一物

有没有办法让真正的方法调用保持接口呢?

chy5wohz

chy5wohz1#

我认为您希望在要调用实际方法的字段上使用@Spy注解,而不是@Mock注解。不过,我碰巧没有示例来验证这一点。https://javadoc.io/doc/org.mockito/mockito-core/2.21.0/org/mockito/Spy.html
然后你就可以做doCallRealMethod().when(clientService.isExistFkUnitId(Mockito.any()))了。因为对于一个间谍对象,你调用的是doReturn/when而不是when/doReturn。https://javadoc.io/doc/org.mockito/mockito-core/2.21.0/org/mockito/Mockito.html#do_family_methods_stubs

kd3sttzy

kd3sttzy2#

好吧,没有“真正的”方法可调用。(忽略接口中的默认方法是当今的一个事实)
一般来说,单元测试应该以独立的方式为目标类编写。像这样,你总是在“测试”“isExistFkUnitId”方法。你可以为特定的值设置模拟:

Mockito.when(clientService.isExistFkUnitId("valueA").thenReturn("answerA");
Mockito.when(clientService.isExistFkUnitId("valueB").thenReturn("answerB");

不管怎样...回答你的问题:
如果可能的话,您可以以所需方法正在工作的方式示例化实现,并通过mock调用它:

ClientServiceImpl clientServiceImpl = new ClientServiceImpl(...);
// spaghetti code only for demonstration purposes ;)
Mockito.when(clientService.isExistFkUnitId(Mockito.any())).then(i -> clientServiceImpl.isExistFkUnitId((String) i.getArguments()[0]));

POC测试:

@Test
public void testit() {
    Myclass myclass = new Myclass();
    Myinterface mock = Mockito.mock(Myinterface.class);
    Mockito.when(mock.myMethod(Mockito.any())).then(i -> myclass.myMethod((String) i.getArguments()[0]));

    assertThat(mock.myMethod(" works")).isEqualTo("yeehaa works");
}

public interface Myinterface {
    String myMethod(String params);
}

public static class Myclass implements Myinterface {
    @Override
    public String myMethod(String params) {
        return "yeehaa" + params;
    }
}

不完全是一个美丽的解决方案,但如果没有办法绕过它,它应该工作。

svdrlsy4

svdrlsy43#

当你模拟一个接口时,Mockito不知道你指的是哪个实现。唯一的方法是使用类。

相关问题