Как я могу проверить, вызывает ли метод класса другой метод из одного из частных объектов классов - PullRequest
0 голосов
/ 01 июня 2019

Я пытаюсь создать модульные тесты для проекта.В моем проекте у меня есть класс меню и класс VerticalOptions.

Мой класс меню имеет частный объект VerticalOptions и открытый метод handleInput.Когда я вызываю метод handleInput (key) моего меню, в зависимости от ключа, который я ему даю, он будет делать разные вещи, а именно вызывать разные методы моего объекта VerticalOptions.

Я хочу сделать unitTest, чтобы увидеть,вызываемые методы являются правильными, как я могу это сделать?

Я пытался добавить шпион Mockito в свое меню, однако, так как я хочу проверить, был ли вызываемый метод методом в частных VerticalOptionsобъект, он на самом деле не работает.

Я также пытался поместить шпиона в объект VerticalOptions после получения его методом getVerticalOptions, но он также не работает.

public void handleInput(InputKey key)
{
    switch (key) {
        case S:
        case DOWN:
            optionsInterface.cycleDown();
            break;
        case W:
        case UP:
            optionsInterface.cycleUp();
            break;
        case SPACE:
        case ENTER:
            optionsInterface.select();
            break;
        default:
            break;
    }
}


@Test
public void testInput() {
    MainMenu menu = new MainMenu(game);
    VerticalButtonInterface buttonInterface = menu.getOptionsInterface();
    VerticalButtonInterface spy = spy(buttonInterface);

    menu.handleInput(InputKey.DOWN);
    verify(spy, times(1)).cycleDown();
}

Это тестовый сбой, который я получил:

Требуется, но не вызывается: verticalButtonInterface.cycleDown ();-> at MenuTest.testInput (MenuTest.java:60) На самом деле, с этим макетом было нулевое взаимодействие.

1 Ответ

1 голос
/ 01 июня 2019

Я дам вам альтернативный взгляд на это.Я видел много людей, идущих по неверному пути, и когда вы делаете это, все остальное становится трудно делать / тестировать, и это именно то, что вы делаете сейчас.

Начните здесь, что вы пытаетесь сделатьдостижения?

Я хочу проверить и убедиться, что определенный метод называется ...

Это хорошо?Что такое модульный тест, который не должен иметь?Это глубокое знание кода.

Почему?Потому что каждый раз, когда вы вносите небольшие изменения в код, вам придется менять тест из-за этого глубокого знания.если у вас 1000 тестов, вам предстоит трудный путь.

Хорошо, теперь мы знаем, в чем проблема, и как мы ее решим?Ну, во-первых, давайте удостоверимся, что у нас может быть тест без глубокого знания кода.

Как мы это делаем?Хорошо, представьте, что ваш код добавляет дополнительный шаг, флаг, который устанавливает состояние.У вас может быть флаг, который хранит результирующее состояние ...

у вас есть 3 метода, которые вы хотите вызвать, поэтому вам понадобятся 3 различных состояния, поэтому создайте переменную, которая отражает это, будь то строка илиперечисление или что-то еще делает вас счастливыми.

Например, ради, скажем, мы создаем строку с 3 возможными значениями: cycleDown, cycleUp и select.

ваш код начинает выглядеть примерно так:

public string handleInput(InputKey key)
{
      String state = determineState(key);
      SomeType someResult = executeActionForState(state);
}

public String determineState(string key)
{

    String state = "";
     switch (key) {
    case S:
    case DOWN:
        state = "cycleDown";
        break;
    case W:
    case UP:
        state = "cycleUp";
        break;
    case SPACE:
    case ENTER:
        state = "select";
        break;
    default:
        break;
}

return state;
}

public void executeActionForState(string state)
{
     if ( state == "cycleup" ) {
     }

     etc etc
}

Теперь я не обязательно кодирую ваш пример, как этот, это немного принудительно, это зависит от того, что вы делаете с кодом, но это должно показать, как вы разделяетефункциональность от аспектов пользовательского интерфейса.

Я могу легко протестировать метод состояния, я могу изменить его код, и мне не придется менять тест, потому что тест будет смотреть на входы и выходы, а не на то, как все достигается.

Модульное тестирование - это функциональность, это простые тесты, которые не нужно менять после создания.Проверка того, что метод был вызван, не даст вам ничего стоящего, потому что вы не знаете, что этот метод делает позже.

Пользовательский интерфейс, который вы можете протестировать другими способами, модульное тестирование - это только правильная функциональность.Если вы не проясните это разделение, у вас будут проблемы с поддержанием ваших тестов, они будут становиться все сложнее и сложнее, пока вы не сдадитесь.

Вы проверите, что получили правильное состояние, а затем протестируете этот метод cycleUpделает что-то правильно, основываясь на ваших требованиях, и именно так вы знаете, что каждая часть работает изолированно.Позже вы начнете рассматривать интеграционные тесты, автоматические тесты пользовательского интерфейса, но это разные вещи.Проведите модульное тестирование того, что он должен делать, сделайте его простым, не привязывайте его к другому коду, и тогда все станет просто.Вам не нужно много издеваться, вам не нужно слишком беспокоиться о сложных настройках, и вам не нужно будет менять свои тесты каждый раз, когда что-то в коде меняется.

Теперь, чтобы рассмотреть заключительную часть вопроса, частные методы, вы проверяете их, наблюдая за их результатами.В вашем классе должно быть что-то общедоступное, которое изменяется при вызове частного метода.Так что проверь это.

...