使用Mockito模拟void方法 [英] Mocking void methods using Mockito

查看:120
本文介绍了使用Mockito模拟void方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我似乎无法在Mockito上模拟void方法.它给出了未完成的存根检测到此处错误.这是我的课程文件.

I cannot seem to mock void methods on Mockito. It gives a unfinished stubbing detected here error. Here is my classfile.

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);
}
}

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

Can someone point out what I am doing wrong please ?

推荐答案

/* system */  public static void mainMenu(IntegerAsker asker){ ... }
/*  test  */  Mockito.doNothing().when(mock).mainMenu(asker);

您的问题不是关于模拟void方法,而是关于模拟static方法,而Mockito无法做到.在后台,Mockito正在创建模拟/监视类(BibliotecaApp)的覆盖以覆盖每个方法,但是由于static方法不能以相同的方式覆盖,因此Mockito不能更改mainMenu的行为-甚至只是为了检测到您在存根中调用了它,这就是为什么它显示为未完成的存根"的原因.

Your problem isn't about mocking void methods, it's about mocking static methods, which Mockito can't do. Behind the scenes, Mockito is creating an override of your mocked/spied class (BibliotecaApp) to override each of the methods, but because static methods can't be overridden the same way, Mockito can't change mainMenu's behavior—even just to detect that you called it in the stubbing, which is why this shows up as "unfinished stubbing".

mainMenu删除static修饰符,您将克服障碍.

Remove the static modifier from mainMenu and you'll be over that hurdle.

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

Side note: You also spy on a class but keep the original around. This isn't a good idea in Mockito: A spy actually creates a copy of the object, so if you're relying on behavior that applies to the spy, you'll have to call the test methods on the spy. (This is part of the reason to avoid spies in your tests: using spies can blur the line between testing your system's behavior and testing Mockito's behavior.)

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)

这篇关于使用Mockito模拟void方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆