[英]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对这种方法进行单元测试?
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.