【问题标题】:Mocking void methods using Mockito使用 Mockito 模拟 void 方法
【发布时间】:2016-02-05 11:54:29
【问题描述】:

我似乎无法在 Mockito 上模拟 void 方法。它给出了一个未完成的存根检测到这里错误。这是我的类文件。

package com.twu.biblioteca;

import java.io.InputStream;
import java.io.PrintStream;
import java.util.InputMismatchException;
import java.util.Scanner;

public class BibliotecaApp {

public static class IntegerAsker {
    private final Scanner scanner;
    private final PrintStream out;

    public IntegerAsker(InputStream in, PrintStream out) {
        scanner = new Scanner(in);
        this.out = out;
    }

    public int ask(String message) {
        out.print(message);
        return scanner.nextInt();
    }
}

public static int numberOfBooks = 0;

public static class book{
    int serialNo;
    String name;
    String author;
    int publication;
    int checkoutstatus;

    book(){
        serialNo = -1;
        name = null;
        author = null;
        publication = -1;
        checkoutstatus = -1;
    }

    book(int serialNo,String name, String author, int publication){
        this.serialNo = serialNo;
        this.name = name;
        this.author = author;
        this.publication = publication;
        this.checkoutstatus=checkoutstatus = 1;
    }
}

public static int getBoundIntegerFromUser(IntegerAsker asker,String message,int lowerBound,int upperBound) {
    int input;
    try
    {
        input = asker.ask(message);
        while(input>upperBound || input<lowerBound)
            input = asker.ask("Select a valid option! ");
            return input;

    }
    catch(InputMismatchException exception)
    {
        System.out.print("You have selected an invalid option! ");
    }
    return -1;
}

public static book[] booksList = new book[20];


public static String welcome(){
    IntegerAsker asker = new IntegerAsker(System.in,System.out);
    return "**** Welcome Customer! We are glad to have you at Biblioteca! ****";

}

public static void addBooks(){
    book newBook1 = new book(1,"Head First Java","Bert Bates",2014);
    booksList[1] = newBook1;
    numberOfBooks += 1;

    book newBook2 = new book(2,"1000 IT Quizzes","Dheeraj Malhotra",2009);
    booksList[2] = newBook2;
    numberOfBooks += 1;

    book newBook3 = new book(3,"100 Shell Programs in Unix","Shivani Jain",2009);
    booksList[3] = newBook3;
    numberOfBooks += 1;

}

public static void mainMenu(IntegerAsker asker){

    System.out.println("1 " + "List Books");
    System.out.println("2" + " Checkout a Book");
    System.out.println("3 " + "Quit");
    int n = getBoundIntegerFromUser(asker,"Enter your choice. ",1,3);
    mainMenuaction(n,asker);
}

public static void mainMenuaction(int n,IntegerAsker asker){
    if(n==1){
        showBooks();
        mainMenu(asker);
    }
    else if(n==2){
        checkout(asker);
    }
    else if(n==3){
        return;
    }
}

public static void showBooks(){
    for(int i=1;i<=numberOfBooks;i++){
        if(booksList[i].checkoutstatus!=0)
        System.out.println(booksList[i].serialNo + ".\t" + booksList[i].name + "\t" + booksList[i].author + "\t" + booksList[i].publication);
    }
}

public static void checkout(IntegerAsker asker){
    int Input = asker.ask("Enter the serial numebr of the book that you want to checkout");
    if(booksList[Input]!=null){
        if(booksList[Input].checkoutstatus!=0){
            booksList[Input].checkoutstatus=0;
            System.out.println("Thank you! Enjoy the book");
        }
        else{
            System.out.println("That book is not available.");
        }
    }
    else{
        System.out.println("That book is not available.");
    }

    mainMenu(asker);

}


public static void main(String[] args) {
    System.out.println(welcome());
    addBooks();
    IntegerAsker asker = new IntegerAsker(System.in,System.out);
    mainMenu(asker);
}
}

这是我的测试文件 -

package com.twu.biblioteca;


import org.mockito.Mockito;
import org.mockito.Mockito.*;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.*;


public class ExampleTest {

BibliotecaApp test = Mockito.mock(BibliotecaApp.class);

@Test
public void welcometest() {
    assertEquals("**** Welcome Customer! We are glad to have you at Biblioteca! ****",test.welcome());
}

@Test
public void addBooksTest(){
    test.addBooks();

    assertEquals("Head First Java",test.booksList[1].name);
    assertEquals("Dheeraj Malhotra",test.booksList[2].author);
    assertEquals(2009,test.booksList[3].publication);
}

@Test
public void getBoundIntegerFromUserTest(){
    BibliotecaApp.IntegerAsker asker = mock(BibliotecaApp.IntegerAsker.class);
    when(asker.ask("Enter your choice. ")).thenReturn(99);
    when(asker.ask("Select a valid option! ")).thenReturn(1);

    BibliotecaApp.getBoundIntegerFromUser(asker,"Enter your choice. ",1,2);

    verify(asker).ask("Select a valid option! ");
}

@Test
public void mainMenuTest(){
    BibliotecaApp.IntegerAsker asker = mock(BibliotecaApp.IntegerAsker.class);

    when(asker.ask("Enter your choice. ")).thenReturn(3);
    test.mainMenu(asker);

    verify(test).mainMenuaction(1,asker);
}

@Test
public void checkoutTest(){
    BibliotecaApp.IntegerAsker asker = mock(BibliotecaApp.IntegerAsker.class);
    BibliotecaApp test = new BibliotecaApp();
    BibliotecaApp mock = spy(test);
    when(asker.ask("Enter the serial numebr of the book that you want to checkout")).thenReturn(2);
    Mockito.doNothing().when(mock).mainMenu(asker);

    test.addBooks();
    test.checkout(asker);


    assertEquals(0,test.booksList[2].checkoutstatus);
}
}

有人可以指出我做错了什么吗?

【问题讨论】:

  • Mockito.doNothing() 是我收到错误的那一行!很抱歉给您带来不便!
  • 请考虑更新问题以使被测类和测试类尽可能小(一个静态方法,一个测试用例)。这将使问题更容易回答。

标签: unit-testing junit mockito


【解决方案1】:
/* system */  public static void mainMenu(IntegerAsker asker){ ... }
/*  test  */  Mockito.doNothing().when(mock).mainMenu(asker);

您的问题不在于模拟 void 方法,而在于模拟 static 方法,而 Mockito 无法做到这一点。在幕后,Mockito 正在创建一个对您的模拟/间谍类 (BibliotecaApp) 的覆盖以覆盖每个方法,但是因为 static 方法不能以相同的方式被覆盖,Mockito 无法更改 mainMenu的行为——甚至只是为了检测到您在存根中调用了它,这就是为什么这会显示为“未完成的存根”。

mainMenu 中删除static 修饰符,您将克服这个障碍。


旁注:您还监视某个课程,但保留原件。这在 Mockito 中不是一个好主意:间谍实际上会创建对象的副本,因此如果您依赖适用于间谍的行为,则必须调用测试方法关于间谍。 (这是在测试中避免使用间谍的部分原因:使用间谍会模糊测试系统行为和测试 Mockito 行为之间的界限。)

BibliotecaApp test = new BibliotecaApp();
BibliotecaApp mock = spy(test);
when(asker.ask("...")).thenReturn(2);
Mockito.doNothing().when(mock).mainMenu(asker);

test.addBooks();           // should be: mock.addBooks()
test.checkout(asker);      // should be: mock.checkout(asker)

【讨论】:

    猜你喜欢
    • 2011-01-17
    • 1970-01-01
    • 2021-02-04
    • 2014-09-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多