如何对 void 函数进行单元测试?

use*_*443 5 java junit unit-testing

class Elephant extends Animal {   
    public Elephant(String name) {
        super(name);
    }

    void makeNoise() {
        logger.info(" Elephant  make Sound");
    }

    void perform(String day) {
        if (day.equals("thursday") || day.equals("friday")) {
            makeNoise();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我想测试一下这个perform方法。如何使用 JUnit 对该方法进行单元测试?

Mar*_*szS 7

Mockito Spy 的解决方案

import org.junit.Test;

import static org.mockito.Mockito.*;

public class ElephantTest {

    @Test
    public void shouldMakeNoise() throws Exception {

        //given
        Elephant elephant = spy(new Elephant("foo"));

        //when
        elephant.perform("friday");

        //then
        verify(elephant).makeNoise();

    }
}
Run Code Online (Sandbox Code Playgroud)

阴性测试:

@Test
public void elephantShouldDontMakeNoisesOnMonday() {

    //given
    Elephant elephant = spy(new Elephant("foo"));

    //when
    elephant.perform("monday");

    //then
    verify(elephant, never()).makeNoise();

}
Run Code Online (Sandbox Code Playgroud)

或者

@Test
public void shouldDoNotMakeNoisesOnMonday() {

    //given
    Elephant elephant = spy(new Elephant("foo"));

    //when
    elephant.perform("monday");

    then(elephant).should(never()).makeNoise();

}
Run Code Online (Sandbox Code Playgroud)

依赖性

org.mockito:mockito-core:2.21.0
Run Code Online (Sandbox Code Playgroud)

阅读


Saz*_*man 1

要测试任何方法,必须通过更改任何变量的状态从方法的外部看到要测试的责任。

通常,它是通过从方法返回值来完成的。但如果没有这个,可以通过从方法范围之外修改某些内容来通过多种方式来完成,以防万一您在从方法返回某些内容时遇到任何“问题”!

就您而言,您只记录一些消息。从某种意义上说,您的代码并不是真正可测试的,因为它不会执行与更改任何变量的状态直接相关的操作(因为您更改了变量以外的其他资源的状态,因此您的代码无法直接访问该资源。您必须编写一些代码来读取外部资源的更改,因此使您的测试代码也依赖于读取。如果您在读取方面遇到问题,您的测试用例将无法通过,这不符合本单元的精神测试。主要思想是尽可能减少对外部代码或库的依赖)。但是您的代码可以通过进行轻微的重构/转移责任来进行测试,如下所示:

String makeNoise() {
    return "Elephant  make Sound";
}

String perform(String day) {
    if (day.equals("thursday") || day.equals("friday")) {
      return makeNoise();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,您将记录从perform方法返回的值的责任转移到使用该方法的值,如下所示:

 logger.info(perform(day));
Run Code Online (Sandbox Code Playgroud)