Contents

EasyMock 模拟 void 方法

1. 概述

模拟框架用于模拟与依赖项的交互,以便单独测试我们的类。通常,我们模拟依赖项以返回各种可能的值。这样,我们可以确保我们的类可以处理这些值中的每一个。

但是,有时我们可能不得不模拟不返回任何内容的依赖方法。

在本教程中,我们将了解何时以及如何使用 EasyMock 模拟void方法。

2. Maven依赖

首先,让我们将EasyMock 依赖 添加到我们的pom.xml中:

<dependency>
    <groupId>org.easymock</groupId>
    <artifactId>easymock</artifactId>
    <version>4.0.2</version>
    <scope>test</scope>
</dependency>

3. 何时模拟void方法

当我们测试具有依赖项的类时,我们通常希望覆盖依赖项返回的所有值。但有时,依赖方法不返回值。那么,如果什么都不返回,我们为什么要模拟一个void方法呢?

即使 void 方法不返回值,它们也可能有副作用。 *Session.save()*方法就是一个例子。当我们保存一个新实体时,*save()*方法会生成一个 id 并将其设置在传递的实体上。

出于这个原因,我们必须模拟 void 方法来模拟各种处理结果。

模拟可能派上用场的另一个时候是在测试 void 方法抛出的异常时。

4. 如何模拟一个void方法

现在,让我们看看如何使用 EasyMock 模拟 void 方法。

假设,我们必须模拟WeatherService类的 void 方法,该方法获取位置并设置最低和最高温度:

public interface WeatherService {
    void populateTemperature(Location location);
}

4.1.创建模拟对象

让我们首先为WeatherService创建一个模拟:

@Mock
private WeatherService mockWeatherService;

在这里,我们使用 EasyMock 注解*@Mock完成了这项工作。但是,我们也可以使用EasyMock.mock()*方法来做到这一点。

接下来,我们将通过调用*populateTemperature()*来记录与模拟的预期交互:

mockWeatherService.populateTemperature(EasyMock.anyObject(Location.class));

现在,如果我们不想模拟这个方法的处理,这个调用本身就足以模拟这个方法。

4.2. 抛出异常

首先,让我们来测试一下我们的类是否可以处理void 方法抛出的异常的情况。为此,我们必须以抛出这些异常的方式模拟该方法。

在我们的示例中,该方法抛出ServiceUnavailableException

EasyMock.expectLastCall().andThrow(new ServiceUnavailableException());

如上所示,这涉及简单地调用*andThrow(Throwable)*方法。

4.3. 模拟方法行为

如前所述,我们有时可能需要模拟 void 方法的行为。

在我们的例子中,这将涉及填充经过位置的最低和最高温度:

EasyMock.expectLastCall()
  .andAnswer(() -> {
      Location passedLocation = (Location) EasyMock.getCurrentArguments()[0];
      passedLocation.setMaximumTemparature(new BigDecimal(MAX_TEMP));
      passedLocation.setMinimumTemperature(new BigDecimal(MAX_TEMP - 10));
      return null;
  });

在这里,我们使用了*andAnswer(IAnswer)方法来定义调用populateTemperature()方法时的行为。然后,我们使用EasyMock.getCurrentArguments()*方法——返回传递给模拟方法的参数——来修改传递的位置。

请注意,我们最后**返回了null。**这是因为我们在模拟一个 void 方法。

还值得注意的是,这种方法不仅限于模拟 void 方法。我们也可以将它用于返回值的方法。在那里,当我们想要模拟方法以根据传递的参数返回值时,它会派上用场。

4.4. 重放模拟方法

最后,我们将使用*EasyMock.replay()*方法将模拟更改为“重播”模式,以便在调用时可以重播记录的动作:

EasyMock.replay(mockWeatherService);

因此,当我们调用测试方法时,应该执行定义的自定义行为。