拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 使用Mockito模拟静态方法

使用Mockito模拟静态方法

白鹭 - 2021-11-24 610 0 0

1.概述

通常,在编写单元测试时,我们会遇到需要模拟静态方法的情况。在Mockito的3.4.0版本之前,不可能直接模拟静态方法–仅在PowerMockito的帮助下

在本教程中,我们将研究如何使用最新版本的Mockito模拟静态方法。要了解有关使用Mockito进行测试的更多信息,请查看我们全面的Mockito系列。

2.一个简单的静态实用程序类

在整个教程中,我们测试的重点将是一个简单的静态实用程序类:

public class StaticUtils {



 private StaticUtils() {}



 public static List<Integer> range(int start, int end) {

 return IntStream.range(start, end)

 .boxed()

 .collect(Collectors.toList());

 }



 public static String name() {

 return "1ju.org";

 }

 }

为了演示的目的,我们有一个方法带有一些参数,而另一种方法仅返回String

3.依存关系

让我们开始吧,向我们的pom.xml mockito-inline依赖项:

<dependency>

 <groupId>org.mockito</groupId>

 <artifactId>mockito-inline</artifactId>

 <version>3.8.0</version>

 <scope>test</scope>

 </dependency>

值得注意的是,在某些时候,根据文档,此功能很可能已集成到更熟悉的mockito-core依赖中。

4.快速测试静态方法

一般来说,有人可能会说,在编写干净的面向对象的代码时,我们不需要模拟静态类。这通常可能暗示我们的应用程序中存在设计问题或代码异味。

首先,因为依赖于静态方法的类具有紧密的耦合,其次,它几乎总是导致难以测试的代码。理想情况下,类不应负责获取其依赖项,并且如果可能的话,应该从外部注入它们。

因此,始终值得研究是否可以重构代码以使其更具可测试性。当然,这并非总是可能的,有时我们不得不模拟静态方法。

5.模拟一个无参数的静态方法

让我们继续前进,看看如何从StaticUtils类中name

@Test

 void givenStaticMethodWithNoArgs_whenMocked_thenReturnsMockSuccessfully() {

 assertThat(StaticUtils.name()).isEqualTo("Baeldung");



 try (MockedStatic<StaticUtils> utilities = Mockito.mockStatic(StaticUtils.class)) {

 utilities.when(StaticUtils::name).thenReturn("Eugen");

 assertThat(StaticUtils.name()).isEqualTo("Eugen");

 }



 assertThat(StaticUtils.name()).isEqualTo("1ju.org");

 }

如前所述,自Mockito 3.4.0起,我们可以使用Mockito.mockStatic( Class<T> classToMock )方法来模拟对静态方法调用的调用。此方法MockedStatic对象,这是一个有范围的模拟对象。

因此,在上面的单元测试中, utilities变量表示具有线程局部显式作用域的模拟。重要的是要注意,作用域模拟必须由激活该模拟的实体关闭。这就是为什么我们在try-with-resources构造中定义模拟程序的原因,以便当我们完成作用域块时自动关闭模拟程序。

这是一个特别不错的功能,因为它可以确保我们的静态模拟仍然是临时的。众所周知,如果在测试运行过程中使用静态方法调用,由于运行测试的并发性和顺序性,这很可能对测试结果造成不利影响。

最重要的是,另一个好处是我们的测试仍然可以超级快速地运行,因为Mockito不需要为每个测试都替换类加载器。

在我们的示例中,我们通过在作用域块之前和之后检查静态方法name返回实值来再次重申这一点。

6.用参数模拟静态方法

现在,让我们看看需要模拟带有参数的方法时的另一个常见用例:

@Test

 void givenStaticMethodWithArgs_whenMocked_thenReturnsMockSuccessfully() {

 assertThat(StaticUtils.range(2, 6)).containsExactly(2, 3, 4, 5);



 try (MockedStatic<StaticUtils> utilities = Mockito.mockStatic(StaticUtils.class)) {

 utilities.when(() -> StaticUtils.range(2, 6))

 .thenReturn(Arrays.asList(10, 11, 12));



 assertThat(StaticUtils.range(2, 6)).containsExactly(10, 11, 12);

 }



 assertThat(StaticUtils.range(2, 6)).containsExactly(2, 3, 4, 5);

 }

如我们所见,除了这次,我们使用了与lambda表达式相同的方法,除了这次,我们在when子句中使用了lambda表达式。非常简单!

7.结论

在这篇快速的文章中,我们已经看到了一些示例,这些示例说明了如何使用Mockito模拟静态方法。总之,Mockito通过一个较小的lambda为狭窄的模拟静态对象提供了一种范围更广的解决方案。

标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *