【问题标题】:Mockito verify constructor calls methodMockito 验证构造函数调用方法
【发布时间】:2018-09-28 14:59:42
【问题描述】:

我正在尝试测试 Game 类何时被实例化,start 方法被调用。但是我收到以下错误:

Wanted but not invoked:
game.start();
Actually, there were zero interactions with this mock.

我有一个名为Game的类

public class Game {
    private Hand player_hand;
    private Hand dealer_hand;
    public static Boolean isInPlay;

    public Game() {
        player_hand = new Hand();
        dealer_hand = new Hand();
        start();
    }

    public void start() {
        isInPlay = true;
        player_hand.hit();
        player_hand.hit();
        System.out.println("Player hand: ");
        player_hand.printHands();
        instantWinLose();
        dealer_hand.hit();
        dealer_hand.hit();
    }
}

我有一个名为GameTest的测试类

@RunWith(MockitoJUnitRunner.StrictStubs.class)

public class GameTest {

@InjectMocks
Game game;

@Mock
Hand hand;

    @Test
    public void testGameConstruction() {
        Game mockedGame = mock(Game.class);
        verify(mockedGame, times(1)).start();
    }
}

我是 Mockito 的新手。我在Difference between @Mock and @InjectMocks 中尝试过以下示例,但我仍然遇到同样的错误

【问题讨论】:

    标签: java unit-testing mocking mockito


    【解决方案1】:

    当您调用 Mockito.mock(SomeType.class) 时,Mockito 将为该类型动态创建一个子类,但对于实例化,它使用某些技术来避免调用超级构造函数 (read more)。

    试试这个:

    public class Foobar {
    
        public Foobar () {
            throw new RuntimeException();
        }
    
    }
    
    // Somewhere else ...
    Mockito.mock(Foobar.class); // No exception will be thrown because constructor is never called
    

    仔细想想,这是有道理的:一个新的模拟对象不应该做任何事情,除非它是绝对需要的(存根)。调用任何真实的逻辑都可能产生不良的副作用。

    这就是为什么你从不模拟被测类本身!

    当你模拟被测类本身时,你的测试完全没有任何意义!

    仅模拟依赖项。

    您的 Game 类没有依赖项,因此您不需要任何模拟:

        @Test
        public void testGameConstruction() {
            Game game = new Game();
            assertTrue(game.isInGame());
        }
    

    如果Game 有依赖关系,例如Hand,你可以添加构造函数参数:

    public Game (Hand hand1, Hand hand2) { .... }
    

    然后:

        @Test
        public void testGameConstruction() {
    
            Hand handMock1 = Mockito.mock(Hand.class);
            Hand handMock2 = Mockito.mock(Hand.class);
            Game game = new Game(handMock1, handMock2);
    
            verify(handMock1, times(1)).hit();
            verify(handMock2, times(1)).hit();
    
        }
    

    【讨论】:

    • 我的Game当前 不依赖Hand 吗? dependencies.
    • 对不起。我正在寻找一个简单的术语,不想让你感到困惑。你说的对。从 OO 的角度来看,Game 依赖于 Hand,但为了 测试 Game 你不需要知道任何关于 Hand 的事情,因为 Game 在内部处理所有事情并提供无参数构造函数。从测试的角度来看,您大部分时间都想忽略如何 某些东西是如何工作的。你想确保它有效!
    【解决方案2】:

    其实,你需要调用 start 方法,然后只有你的 mocking 会被时间验证。

    类似于 :: mockedGames.start()

    那么只有它调用会被验证

    【讨论】:

      【解决方案3】:

      我的理解是,通过模拟 Game 类,您也可以模拟构造函数。这意味着没有运行来自实际类构造函数的代码。尝试在不模拟的情况下创建 Game 类的实例。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-02-18
        相关资源
        最近更新 更多