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);
因此,当我们调用测试方法时,应该执行定义的自定义行为。