测试是否使用Mockito调用方法

时间:2016-08-14 13:06:58

标签: java unit-testing mocking mockito

我有一个菜单,根据给出的选择调用不同的操作。我想使用mockito来查看是否调用了正确的方法。 这是我到目前为止的实施......

Menu.java:

我的菜单包含不同选项的选项和实例。

例如。 printItemOfTypeBook是PrintBookOperation的一个实例。

    private void setMenuOptions() {
        char keyForPrintingBooks = '1';
        char keyForPrintingMovies = '2';
        char keyForAccountLogin = '3';
        char keyForExit = '4';
        menuOptions.put(keyForPrintingBooks, printItemsOfTypeBook);
        menuOptions.put(keyForPrintingMovies, printItemsOfTypeMovie);
        homeMenuOptions.put(keyForAccountLogin, loginAccount);
        homeMenuOptions.put(keyForExit, quit);
    }

然后我将一个字符传递给apply choice方法,该方法找到适当的实例并在其上调用execute。

    public void applyChoice(char choice) {
        if ((!menuOptions.containsKey(choice)) && (!homeMenuOptions.containsKey(choice))) {
            new WrongChoiceOperation();
        }
        if (menuOptions.containsKey(choice)) {
            menuOptions.get(choice).execute(library, reader, writer);
        }
        if (homeMenuOptions.containsKey(choice)) {
            homeMenuOptions.get(choice).execute(library, reader, writer);
        }
    }
}

我正在测试第一个打印书籍的选项。所以我模拟PrintBookOperation类并检查其中的execute方法是否被调用。

PrintBookOperation.java:

    @Override
    public void execute(Library library, Input reader, Output writer) {
        this.library = library;
        this.writer = writer;
        printBooks();
    }

    private void printBooks() {
        writer.formattedHeadings();
        List<Lendable> items = library.listItems();
        items.stream().filter(item -> item.isOfType(Book)).forEach(item -> {
            writer.write("\n" + item.toFormattedString());
        });
    }
}

我的测试:

    @Test
    public void isThePrintOperationCalled() {
        Input reader = new ConsoleInput();
        Output writer = new ConsoleOutput();
        PrintBooksOperation print = mock(PrintBooksOperation.class);
        Book book = new Book("nin", "#123", "ghy", 2003);
        Library library = new Library(new LinkedList<>(singletonList(book)));
        Menu menu = new Menu(reader, writer, library);
        menu.applyChoice('1');
        verify(print).execute(library, reader, writer);
    }

}

我的错误讯息:

Wanted but not invoked:
printBooksOperation.execute(
    tw51.biblioteca.Library@39c0f4a,
    Mock for Input, hashCode: 1471868639,
    Mock for Output, hashCode: 876563773
);
-> at tw51.biblioteca.io.menu.home.MenuTest.isThePrintOperationCalled(MenuTest.java:30)
Actually, there were zero interactions with this mock.

我做错了什么?我该如何纠正这个?

1 个答案:

答案 0 :(得分:2)

您正在为PrintBooksOperation类创建一个模拟(称为print),但模拟不会发送到正在测试的类。因此,mockito会抛出异常,因为从未在模拟上调用 execute 函数。

我建议更改您的Menu类,以便注入

  • printItemsOfTypeBook
  • printItemsOfTypeMovie
  • 登录账号
  • 退出

而不是在Menu.java中分配新实例。你可以这样做:

public class Menu {
     public Menu(Input reader, 
                Output writer, 
                Library library, 
                PrintBooksOperation printItemsOfTypeBook, 
                PrintMoviesOperation printItemsOfTypeMovie, 
                LoginAccountOperation loginAccount, 
                QuitOperation quit) {
           this.reader = reader;
           this.writer = writer;
           this.library = library;
           this.printItemsOfTypeBook = printItemsOfTypeBook;
           this.printItemsOfTypeMovie = printItemsOfTypeMovie;
           this.loginAccount = loginAccount;
           this.quit = quit;
     }
}

(注意我猜到了上面其他操作类的类名)。现在,在您的测试类中,您可以执行以下操作:

    PrintBooksOperation print = mock(PrintBooksOperation.class);
    Menu menu = new Menu(reader, writer, library, print, null, null, null);
    menu.applyChoice('1');
    verify(print).execute(library, reader, writer);

验证现在应该正常运行。

基本上,如果您为单位使用依赖注入,它会使单元测试变得更加容易。