java - 有没有办法合法地转换 Mockito 模拟对象?

标签 java unit-testing mockito polymorphism discord-jda

我使用 Java 11、JUnit Jupiter 5.6.0、Mockito 3.3.3 和 Java Discord API 4.1.1_122 为我的小型 Discord 机器人编写了几个测试用例类。

我意识到我的测试用例有多个重复行为的实例,包括用于相同目的的相等模拟的声明,以及 given([method call]).willReturn([object]); 的重复。在我的@BeforeEach启动方法。我希望将重复的行为分成基类来组织自己,但我被困住了。 我的所有测试类都测试 Java Discord API 框架中的某种事件处理程序,因此我创建了一个名为 GenericEventTest 的顶级类。 :

public abstract class GenericEventTest {
    @Mock
    protected GenericEvent eventMock;

    @Mock
    protected JDA jdaMock;

    protected GenericEventTest() {
        MockitoAnnotations.initMocks(this);

        given(   eventMock.getJDA()   )
                .willReturn(jdaMock);
    }
}

我希望为该事件实现一个高级模拟,以多态地适应我的测试类,然后将指定的given()命令在它所属的类中,因为我的所有测试都重复同一行。 接下来,我意识到我的所有测试都在测试与 Discord 中的消息相关的某种事件。所以我延长了 GenericEvent并制作GuildMessageEventTest :

public abstract class GuildMessageEventTest extends GenericEventTest {
    @Mock
    protected GenericGuildMessageEvent eventMock;

    @Mock
    protected TextChannel eventChannelMock;

    @Mock
    protected MessageAction messageActionMock;

    protected GuildMessageEventTest() {
        super();

        MockitoAnnotations.initMocks(this);

        given(   eventMock.getChannel()   )
                .willReturn(eventChannelMock);

        given(   eventChannelMock.sendMessage(anyString())   )
                .willReturn(messageActionMock);
    }
}

我的想法是在此类中实现下一个级别的事件,GenericGuildMessageEvent这将具有相同的 given()适用于 GenericEvent 的规则,然后添加适当的 given()这个类(class)的规则。但我相信我已经找到了我的问题。

当我声明@Mock protected GenericGuildMessageEvent eventMock;时我正在跟踪GenericEvent eventMock来自GenericEventTest 。所以,我宣布GenericGuildMessageEvent例如,但我没有保留 given()附加到GenericEventTest中的模拟的规则。做类似 @Mock protected GenericGuildMessageEvent eventMock = (GenericGuildMessageEvent) super.eventMock; 的事情将不起作用,因为用 @Mock 注释的对象不能以这种方式合法类型转换。

我的问题是:我如何合法地向上转换我的 GenericEvent 实例进入GenericGuildMessageEvent同时让 Mockito 复制 given()规则附加到GenericEvent父类(super class)中的实例?

最佳答案

GenericEventTest 中声明一个 abstract GenericEvent getEventMock(); 方法,并让 GuildMessageEventTest 实现它。然后将实例字段 protected GenericEvent eventMock 从基类移动到子类。使用 getEventMock() 访问基类中的模拟。请注意,您的子类中不再需要 MockitoAnnotations.initMocks(this); 。这将覆盖基类中的模拟行为。

// GenericEventTest
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import static org.mockito.BDDMockito.given;

public abstract class GenericEventTest {

    protected GenericEventTest() {
        MockitoAnnotations.initMocks(this);

        given(getEventMock().getJDA()).willReturn("jdaMock");
    }

    abstract GenericEvent getEventMock();
}

// GuildMessageEventTest
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import static org.mockito.BDDMockito.given;

public abstract class GuildMessageEventTest extends GenericEventTest {
    @Mock
    protected GenericGuildMessageEvent eventMock;

    @Mock
    protected GenericGuildMessageEvent myMock;

    @Override
    public GenericGuildMessageEvent getEventMock() {
        return eventMock;
    }

    protected GuildMessageEventTest() {
        super();

//        MockitoAnnotations.initMocks(this);

        given(eventMock.getChannel())
                .willReturn("eventChannelMock");

    }
}

//The Test
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

public class ActualMessageTest extends GuildMessageEventTest {

    @org.junit.jupiter.api.Test
    public void testX() {
        assertEquals("eventChannelMock", eventMock.getChannel());
        assertEquals("jdaMock", eventMock.getJDA());
        assertNotNull(myMock);
    }

}

关于java - 有没有办法合法地转换 Mockito 模拟对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60871568/

相关文章:

java - key 斗篷错误 : Unrecognized field "access_token"

angular - 如何将任何 URL 与 HttpTestingController.expectOne 匹配?

java - Intellij 不将 Mockito 类识别为测试类

java - 单元测试和模拟工厂

java - 树形图构造函数

java - 如何使用 Java comm API 处理读取超时

unit-testing - Angular2 RC5 如何正确配置测试模块

c# - Moq 框架对返回任务的方法进行单元测试

java - 用 Mockito 验证一个函数被调用的次数有什么意义?

java - 在 Mockito 中验证交替调用