有没有一种方法可以合法地投射Mockito模拟对象?

时间:2020-03-26 16:17:04

标签: 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规则,然后添加适当的{{ 1}}此类中的规则。但是我相信我已经找到了问题。

当我声明given()时,我正在{strong>遮蔽来自@Mock protected GenericGuildMessageEvent eventMock;的{​​{1}}。因此,我声明了GenericEvent eventMock实例,但是我没有保留 GenericEventTest中附加到该模拟的规则GenericGuildMessageEvent。进行given()之类的操作将不起作用,因为用GenericEventTest注释的对象不能以这种方式合法地投射。

我的问题是:在让Mockito复制附加到@Mock protected GenericGuildMessageEvent eventMock = (GenericGuildMessageEvent) super.eventMock;实例的@Mock规则的同时,如何合法地将我的GenericEvent实例上传到GenericGuildMessageEvent中在超类中?

1 个答案:

答案 0 :(得分:1)

在您的abstract GenericEvent getEventMock();中声明一个GenericEventTest方法,并让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);
    }

}
相关问题