繁体   English   中英

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

[英]How can I unit test void functions?

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

现在我要测试perform方法。 如何使用JUnit对这种方法进行单元测试?

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

    }
}

阴性测试:

@Test
public void elephantShouldDontMakeNoisesOnMonday() {

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

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

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

}

要么

@Test
public void shouldDoNotMakeNoisesOnMonday() {

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

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

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

}

相依性

org.mockito:mockito-core:2.21.0

阅读

void()函数更改程序的状态。 这可以通过修改变量,文件,数据库等来完成。

就您而言,您是在写记录器。 如果这导致将“ Elephant make Sound”写入文件,则可以读取该文件并查看文件中的数据是否包含您的嘈杂的大象。

但是,如果它不涉及任何内容,您可以检查(即:它仅在控制台上显示输出),则可能需要查看某种形式的依赖项注入(DI),您可以在其中将输出设置为文件或其他内容您可以轻松阅读。

应该注意的是,您可以通过模拟对象并检查是否调用了适当的方法来绕过DI。

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

通常,它是通过从方法返回值来完成的。 但是,如果没有任何“问题”可以从方法返回值,则可以通过多种方法来修改方法范围之外的内容,从而完成此操作!

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

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

String perform(String day) {
    if (day.equals("thursday") || day.equals("friday")) {
      return makeNoise();
    }
}

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

 logger.info(perform(day));

根据您愿意使用的工具和测试的深度,您可以有多种选择。

用纯Java进行部分模拟

创建一个从Elephant扩展的类(MockElephant),覆盖makeNoise以便计算调用次数。 在测试中使用该类来检查makeNoise已正确调用makeNoise次数

部分嘲讽与框架你基本同上,但代替手工编码MockElephant创建使用一些模拟框架它。 由于您需要更少的代码,因此使测试更加简单。 而且更容易阅读。 但是,如果发生奇怪的事情,则将很难理解发生了什么。 对于模拟框架,我认为它们是值得的。

之所以称为“部分模拟”,是因为您仅模拟类的一部分(在这种情况下为单个方法)。

另一种方法是使用Normal Mocks ,在您看来,这是可行的(但在旧代码中可能会变得很难)。

在这里,您需要将Logger注入为依赖项。 例如,您可以创建一个附加的构造函数,该构造函数允许您提供Logger。 然后,在测试中,您将使用模拟的Logger,该Logger再次计算其调用次数,并可能连同接收到的参数一起计数,并检查其是否具有预期值。

同样,您可以使用Mocking Framework或普通的Java来实现。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM