gpt4 book ai didi

java - 如何使用 Mockito 消除外部依赖?

转载 作者:行者123 更新时间:2023-11-29 08:36:23 25 4
gpt4 key购买 nike

我在理解 Mockito 的概念时遇到了一些困难。我已经编写了一个小程序来提供帮助,但我无法让它执行我想要的操作。

这是我的代码:

// WeatherDemo.java:

package com.abc;

public class WeatherDemo {
public String getForecast() {
// Get the high remperature for today, and return back to the caller one of these values:
// cold, mild, or hot
// cold will be returned if the high temp is forecast to be less than 60.
// hot will be returned if the high temp is forecast to be more than 79.
// Otherwise, mild will be returned (this indicates a high temp in the 60s or 70s).
int highTemp = getHighTemp();
if (highTemp < 60)
return("cold");
if (highTemp > 79)
return("hot");
return("mild");
}

public int getHighTemp() {
// Because this is a demo, we don't have access to any source (web service, DB, etc.) to get the high temp.
// Just hard code a value here, but remember that if this were a real application, we would be dynamically
// retrieving the day's high temperature from some external source.
int highTemp = 32;
return(highTemp);
}
}

============================================= =================================

// TestWeatherDemo.java:

package com.abc;

import static org.mockito.Mockito.*;
import static org.junit.Assert.*;
import org.junit.Test;
import org.mockito.Mockito;

public class TestWeatherDemo {
@Test
public void testWeatherReport() {
WeatherDemo testMockito = Mockito.mock(WeatherDemo.class);
WeatherDemo testJUnit = new WeatherDemo();

when(testMockito.getHighTemp()).thenReturn(90);
assertEquals("hot", testJUnit.getForecast());
}
}

============================================= =================================

基本上,我想在 getForecast() 上运行 JUnit。它返回寒冷、温和或炎热,这取决于当天的高温。要获得高温,它会调用 getHighTemp()。假设 getHighTemp() 调用 Web 服务来获取温度(为了测试目的,我硬编码了一个值)。因为这是外部资源,所以我的 Junit 没有通过隔离测试,根本不是真正的单元测试。更不用说 getHighTemp() 每次调用时都不会返回相同的值。

因此,我想模拟 getHighTemp(),告诉它始终返回 90 的温度。

Mockito 测试从 testWeatherReport() 运行。这就是我被困的地方。执行此操作时,我可以模拟 getHighTemp() 以返回 90:

当(testMockito.getHighTemp()).thenReturn(90);

但是,当从 getForecast() 调用时,我无法让它返回 90。断言变得“冷”,因为它选择的是 32,而不是 90。

Mockito 背后的整个想法不就是我可以模拟一个方法并准确地告诉它要返回什么,以消除外部依赖吗?如果从 getForecast() 调用 getHighTemp() 不会返回 90,我看不出 Mockito 的用途。我在这里错过了什么?感谢您的帮助和启发。

比尔

最佳答案

您实质上是在问“我如何在测试其余方法的同时模拟类中的一个方法”。可以使用 Mockito - 在文档中搜索“部分模拟”。然而,它(几乎)总是表明您的代码结构不正确并且需要重构。如果您正在测试一个访问您想要模拟的接口(interface)的类,那么这表明您应该将该接口(interface)声明为 interface,然后将实现传递给该类。这有两个作用:首先,它允许您在不更改接口(interface)的情况下更改实现;其次,它使类可测试。

所以在你的情况下:

public interface TempSupplier {
int getHighTemp();
int getLowTemp();
}

public class WeatherDescriber {
private final TempSupplier tempSupplier;

public WeatherDescriber(TempSupplier tempSupplier) {
this.tempSupplier = tempSupplier;
}

public String getForecast() {
int highTemp = tempSupplier.getHighTemp();
...
}
}

@Test
public void testForecast() {
TempSupplier supplier = mock(TempSupplier.class);
when(supplier.getHighTemp()).thenReturn(90);
WeatherDescriber describer = new WeatherDescriber(supplier);
assertThat(describer.getForecast(), is("Hot"));
}

我通常将模拟拆分成一个单独的方法,这样您就可以轻松地进行测试:

private WeatherDescriber getDescriber(int lowTemp, int highTemp) {
TempSupplier supplier = mock(TempSupplier.class);
when(supplier.getLowTemp()).thenReturn(lowTemp);
when(supplier.getHighTemp()).thenReturn(highTemp);
return new WeatherDescriber(supplier);
}

@Test
public void testDescribeVariousTemps() {
assertThat(getDescriber(10, 20).getForecast(), is("cold"));
assertThat(getDescriber(30, 35).getForecast(), is("cold"));
assertThat(getDescriber(40, 45).getForecast(), is("warmer"));
assertThat(getDescriber(90, 130).getForecast(), is("melting"));
}

关于java - 如何使用 Mockito 消除外部依赖?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43858564/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com