我正在使用 Mockito 练习 JUnit,并尝试测试一个简单的静态方法
class LessSimpleCalculatorImp implements LessSimpleCalculator {
@Override
public int power(int x, int y) {
return (int)Math.pow(x, y); // <-- try to see if Math.pow has been called
}
}
测试用例:
@RunWith(MockitoJUnitRunner.class)
public class LessSimpleCalculator_Test {
@Test
public void test_pow() {
try(MockedStatic<Math> mockedMath = Mockito.mockStatic(Math.class);) {
mockedMath.when(() -> Math.pow(3, 2)).thenReturn(9.0);
int result = lessSimpleCalculator.power(3, 2);
assertEquals(9, result);
mockedMath.verify(() -> Math.pow(3, 2), times(1));
}
}
}
当我这样做时,这会给我一个 StackOverflowError
mvn clean test
:
Exception: java.lang.StackOverflowError thrown from the UncaughtExceptionHandler in thread "main"
ChatGPT 说这是因为模拟类调用了 Math.pow,它被模拟类拦截,再次调用真实类。我该如何解决这个问题?
我还使用 Maven 进行依赖管理:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>5.13.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
这似乎是 Mockito 中的一个已知问题,他们不会修复它: https://github.com/mockito/mockito/issues/2105
老实说,无论如何,嘲笑
Math.pow
可以说是一种不好的方法,因为这意味着您的测试需要对 LessSimpleCalculatorImp
的实现有深入的了解。LessSimpleCalculatorImp
的实现,而只关心最终结果 - 您已经知道 3 的 2 次方结果应该是 9(您已经将其作为预期结果)断言!),所以只需测试一下:
@Test
public void test_pow() {
int result = lessSimpleCalculator.power(3, 2);
assertEquals(9, result);
}
顺便说一句,查看您的 pom.xml,您正在混合 JUnit Jupiter 和旧的 JUnit 4。您可能应该与其中之一对齐:
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.11.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>5.13.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.13.0</version>
<scope>test</scope>
</dependency>
</dependencies>
当然,按照我的建议,你无论如何都不需要 Mockito,但我假设你还有其他测试仍然需要它。