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

Mockito@mock不使用when()来存根方法

陈俊郎
2023-03-14

我正在为一个基于著名视频游戏的个人项目开发一个使用Spring Boot和六边形架构的简单REST API。几天前,我使用JUnit5(jupiter)和mockito编写了单元测试。他们工作得很好,但今天我更新了我的测试代码,因为我想为我的API添加i18n支持,以及一个简单的配置,允许禁用玩家和他们的官方Minecraft UUID之间的链接。

我的类的构造函数已经更改,为i18n支持添加了一个MessageSource对象,并为uuid链接状态添加了一个布尔值。我的类现在是这样的:

public class PlayerService implements PlayerApi {

    private final boolean ONLINE_MODE;
    private final PlayerSpi playerSpi;
    private final MojangApi mojangApi;
    private final MessageSource messageSource;

    public PlayerService(PlayerSpi playerSpi, MojangApi mojangApi,
                         boolean onlineMode, MessageSource messageSource) {
        this.playerSpi = playerSpi;
        this.mojangApi = mojangApi;
        this.ONLINE_MODE = onlineMode;
        this.messageSource = messageSource;
    }

    @Override
    public Option<Player> findByPseudoOrEmailAddress(String pseudo, String emailAddress) {
        if (pseudo.isEmpty() || emailAddress.isEmpty()) return Option.none();//TODO BETTER ERROR GEST USING EITHER ?
        return playerSpi.findByPseudoOrEmailAddress(pseudo, emailAddress);
    }

    @Override
    public Option<Player> findById(Long id) {
        return playerSpi.findById(id);
    }

    @Override
    public Boolean existByPseudo(String pseudo) {
        return playerSpi.existByPseudo(pseudo);
    }

    @Override
    public Boolean existByEmailAddress(String emailAddress) {
        return playerSpi.existByEmailAddress(emailAddress);
    }

    @Override
    public void save(Player player) {
        playerSpi.save(player);
    }

    @Override
    public Response<?> register(Player player) {

        //LINK PLAYER TO HIS MINECRAFT UUID IF ONLINE MODE IS TRUE
        if (ONLINE_MODE) {
            Either<MinecraftUUIDException, String> result = mojangApi.getPlayerUUID(player.getPseudo());
            if (result.isRight())
                player.setMinecraftUUID(result.get());
            else
                return Response.Builder.create()
                    .success(false)
                    .message(messageSource.getMessage("PlayerService.register.uuid-linking-failed",
                        null, LocaleContextHolder.getLocale()))
                    .body(result.getLeft())
                    .build();

        }
        save(player);
        return Response.Builder.create()
            .success(true)
            .message(messageSource.getMessage("PlayerService.register.success",
                null, LocaleContextHolder.getLocale()))
            .body(null)
            .build();
    }
}

所以我创建了一个测试类,如下所示:

@ExtendWith(MockitoExtension.class)
@TestInstance(Lifecycle.PER_CLASS)
public class PlayerServiceTest {

    @Mock
    private PlayerSpi playerSpi;
    @Mock
    private MojangApi mojangApi;
    @Mock
    private MessageSource messageSource;
    private PlayerService playerService;

    @BeforeAll
    void setUp() {
        initMocks(this);
        playerService = new PlayerService(
            playerSpi,
            mojangApi,
            true,
            messageSource
        );
    }

    @Test
    void register_should_register() {
        Player p = new Player(
            1L,
            "Bad_Pop",
            "test@test.com",
            "password",
            List.empty(),
            "uuid"
        );

        when(mojangApi.getPlayerUUID(any())).thenReturn(Either.right("uuid"));
        ArgumentCaptor<Player> valueCapture = ArgumentCaptor.forClass(Player.class);
        lenient().doNothing().when(playerSpi).save(valueCapture.capture());

        Response<?> res = playerService.register(p);

        assertEquals(p.getId(), valueCapture.getValue().getId());
        assertEquals(p.getPseudo(), valueCapture.getValue().getPseudo());
        assertEquals(p.getEmailAddress(), valueCapture.getValue().getEmailAddress());
        assertEquals(p.getPassword(), valueCapture.getValue().getPassword());
        assertEquals(p.getRoles(), valueCapture.getValue().getRoles());
        assertEquals(p.getMinecraftUUID(), valueCapture.getValue().getMinecraftUUID());

        assertTrue(res.getSuccess());
        assertTrue("Player successfully registered.".equalsIgnoreCase(res.getMessage()));
        assertNull(res.getBody());
    }

    @Test
    void register_should_not_register() {
        Player p = new Player(
            1L,
            "Bad_Pop",
            "test@test.com",
            "password",
            List.empty(),
            "uuid"
        );

        when(mojangApi.getPlayerUUID(any())).thenReturn(
            Either.left(
                new MinecraftUUIDException("Unable to retrieve Minecraft UUID for this player. Please make sure this player name exists.")
            )
        );

        Response<?> res = playerService.register(p);

        assertFalse(res.getSuccess());
        assertTrue("An error occured while registering this player".equalsIgnoreCase(res.getMessage()));
        assertTrue(res.getBody().getClass().getSimpleName().equalsIgnoreCase("MinecraftUUIDException"));
        MinecraftUUIDException e = (MinecraftUUIDException) res.getBody();
        assertEquals("Unable to retrieve Minecraft UUID for this player. Please make sure this player name exists.",
            e.getMessage());
    }

//remaining tests ommitted
}
java.lang.NullPointerException
    at io.denoria.domain.core.service.PlayerService.register(PlayerService.java:61)
    at io.denoria.domain.PlayerServiceTest.register_should_register(PlayerServiceTest.java:178)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:567)
    at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:675)
    at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:125)
    at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:139)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:131)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:81)
    at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:104)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:62)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:43)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:35)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:202)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:198)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:69)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:135)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:248)
    at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$5(DefaultLauncher.java:211)
    at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:226)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:199)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:132)
    at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:69)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)
    Suppressed: org.mockito.exceptions.misusing.UnnecessaryStubbingException: 
Unnecessary stubbings detected.
Clean & maintainable test code requires zero unnecessary code.
Following stubbings are unnecessary (click to navigate to relevant line of code):
  1. -> at io.denoria.domain.PlayerServiceTest.register_should_register(PlayerServiceTest.java:174)
Please remove unnecessary stubbings or use 'lenient' strictness. More info: javadoc for UnnecessaryStubbingException class.
        at org.mockito.junit.jupiter.MockitoExtension.afterEach(MockitoExtension.java:230)
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeAfterEachCallbacks$11(TestMethodTestDescriptor.java:245)
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeAllAfterMethodsOrCallbacks$12(TestMethodTestDescriptor.java:256)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeAllAfterMethodsOrCallbacks$13(TestMethodTestDescriptor.java:256)
        at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeAllAfterMethodsOrCallbacks(TestMethodTestDescriptor.java:255)
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeAfterEachCallbacks(TestMethodTestDescriptor.java:244)
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:141)
        ... 41 more

我已经在其他类中添加了对i18n的支持,我没有这个问题。

共有1个答案

明阳旭
2023-03-14

initmocks()应该在测试类的每个实例中调用,因此应该在@beforeach方法中调用initmocks()方法中调用initmocks()。此外,@BeforeAll需要一个静态方法--除非您已经切换了生命周期,但您的代码没有显示这一点。

我在想为什么木星不抱怨非静态方法。也许您使用的是JUnit4中的@test?如果您不能用@beforeeach修复这个问题,请在测试类中显示您的所有导入。

 类似资料:
  • 我想通过模拟class的重写方法a1方法2来测试我的服务。我不想更改课程A1和B1中的任何内容。我使用的是mockito 1.9.0和powermockito 1.4.12。我正在尝试以下代码: UnitTestService类: 服务级别: A1类: B1级: 我正在eclipse中使用testNG运行类UnitTestService。在这里,B1类a1Method2中的实际方法在控制台中打印“

  • 问题内容: 我最近已经问了几个有关jUnit和Mockito的问题,但我仍然很努力地把握住这个问题。这些教程都是针对非常简单的示例的,因此我正在努力扩大测试用例以适合我的课程。 我目前正在尝试为Webapp中我的一个代理中的方法编写一些测试用例。该方法与代理内部的其他两种方法交互以验证某些对象。我现在只想测试这种方法。 这是我尝试做的事情: 创建我的代理的Mockito对象,如下所示: 使用Moc

  • 我最近问了几个面向jUnit和Mockito的问题,但我仍然很难掌握其中的诀窍。这些教程都是针对非常简单的示例,所以我很难扩展我的测试用例来为我的类工作。 我目前正试图为我在WebApp中的一个代理中的一个方法编写一些测试用例。该方法与代理内部的几个其他方法交互,以验证某些对象。我现在只想测试一下这个方法。 使用Mockito设置存根(希望是正确的术语)。如下所示: 尝试执行我的方法,如下所示:

  • 这是我的实际服务方法。在测试时,它给我的变量为空。用户和响应 我试图写一个测试用例和模拟方法findByEmail()和保存(),但同时嘲笑我没有收到用户对象在返回中提到的thenback()和doback()。 有人能帮忙吗。

  • 我必须测试一些SLSB的方法,它在当前对象上调用另一个方法(使用这个关键字),我需要以某种方式将它存根。 请考虑以下简化代码: 为了存根getSomeDBValue()方法,我可以使用@mock和@injectMocks注释将mock注入到该类,但我不知道如何正确地存根anotherMethod()。要存根它,我需要在模拟对象上做这件事,所以我尝试将引用传递到当前对象作为参数,在测试中只传递模拟对

  • 下面是正在测试的方法的缩短版本。 一如既往,我们感谢您能提供的任何帮助。

  • 问题内容: 因此,我开始为我们的Java Spring项目编写测试。 我使用的是JUnit和Mockito。有人说,当我使用when()… thenReturn()选项时,可以模拟服务,而无需模拟它们。所以我要做的是设置: 但是无论我执行哪一个子句,我总会得到一个NullpointerException,这当然是有道理的,因为input为null。 另外,当我尝试从对象模拟另一个方法时: 在那里,

  • 我试图通过在传入字符串“John”时返回一个用户对象来建立类(spring-data-jpa存储库)的方法。 发生的情况是,在userService中,当调用users.findbyUsername(“John”)时,它总是返回null,而不是我定义的任何用户对象: 当我在测试方法中放置断点并比较users和UserService.users时,它们是相等的。 pom版本