当前位置: 首页 > 知识库问答 >
问题:

在进行集成测试时,如何正确使用 mockito?

楚昀
2023-03-14

我有一个函数,在这个函数中,我想替换一些组件的行为(余弦,正弦,...),我正在尝试为这些部分创建一个mock,并将它们传递给函数。

class Function1Test {
private static final double accuracy = 10e-5;
static Function1 firstFunction;
static Function2 secondFunction;
static TrFunc.MyCos cos;
static TrFunc.MySin sin;
static TrFunc.MyTan tan;
static TrFunc.MySec sec;
static LgFunc.Log2 log2;
static LgFunc.Log3 log3;
static LgFunc.Log5 log5;
static LgFunc.Log10 log10;
static Func_System sys;
@BeforeAll
static void setUp() {
    cos = mock(TrFunc.MyCos.class);
    sin = mock(TrFunc.MySin.class);
    tan = mock(TrFunc.MyTan.class);
    sec = mock(TrFunc.MySec.class);
    firstFunction = new Function1(cos, sin, tan, sec);
    log2 = mock(LgFunc.Log2.class);
    log3 = mock(LgFunc.Log3.class);
    log5 = mock(LgFunc.Log5.class);
    log10 = mock(LgFunc.Log10.class);
    secondFunction = new Function2(log2, log3, log5, log10);
    sys = new Func_System(firstFunction, secondFunction);
}

static Stream<Arguments> valuesRangeProvider(){
    return Stream.of(
            arguments(-6.282185307179586, 1001001.3330000667),
            arguments(-0.161592653589793, 33.496935752492160)
    );
}
@DisplayName("Integration Test with Mocks")
@ParameterizedTest(name = "{index}: Check range of values, x = {0}")
@MethodSource("valuesRangeProvider")
void test_0(double value, double expected) throws Exception {
    when(firstFunction.sin.mySin(value, accuracy)).thenReturn(sin(value));
    when(firstFunction.cos.myCos(value, accuracy)).thenReturn(cos(value));
    when(firstFunction.tang.myTan(value, accuracy)).thenReturn(sin(value)/cos(value));
    when(firstFunction.sec.mySec(value, accuracy)).thenReturn(1/cos(value));
    assertEquals(expected, firstFunction.calculate(value, accuracy), accuracy);
}

问题是,我收到以下消息:

*org.mockito.exceptions.misusing.MissingMethodInvocationException:当()需要一个必须是“模拟上的方法调用”的参数。例如:当(mock.getArticles()). then返回(文章);此外,这个错误可能会出现,因为:

    < li >您stub了final/private/equals()/hashCode()方法之一。这些方法不能被存根化/验证。不支持模仿在非公共父类上声明的方法。 < li >在when()中,不在mock上调用方法,而是在其他对象上调用方法。*

这些方法都不是私有的或最终的

public class TrFunc {
public static class MyCos {
    public static double myCos(double x, double accuracy) throws Exception {
        if (accuracy < 0){
            throw new Exception("The accuracy below zero");
        }
        double theta_norm = Math.abs(x);
        theta_norm -= Math.floor(theta_norm/Math.PI/2)*2*Math.PI;
        double result = 1;
        double step = 1;
        int i;
        for (i = 1; step > accuracy && i != Integer.MAX_VALUE; i++){
            step = step*theta_norm*theta_norm/(2*i-1)/(2*i);
            if (i % 2 == 1){
                result -= step;
            } else {
                result += step;
            }
        }
        if (!Double.isFinite(result) || i == Integer.MAX_VALUE-1){
            throw new Exception("Too many iterations");
        }
        return result;
    }


    private static double factorial(int numer) {
        double factorial = 1.0d;

        while (numer != 0) {
            factorial *= numer--;
        }

        return factorial;
    }
}

public static class MySin {
    public static double mySin(double x, double accuracy) throws Exception {
        return MyCos.myCos(Math.PI/2 - x, accuracy);
    }
}

public static class MyTan {
    public static double myTan(double x, double accuracy) throws Exception {
        double divisor =  MyCos.myCos(x, accuracy);
        if (Math.abs(divisor) <= accuracy) throw new Exception("Division by zero");
        return MySin.mySin(x, accuracy) / divisor;
    }
}

public static class MySec {
    public static double mySec(double x, double accuracy) throws Exception {
        double divisor =  MyCos.myCos(x, accuracy);
        if (Math.abs(divisor) <= accuracy) throw new Exception("Division by zero");
        if ((x + Math.PI / 2) / Math.PI % 1 == 0) throw new Exception("x can't be Pi*n-Pi/2");
        return 1 / divisor;
    }
}
}

共有1个答案

慕飞章
2023-03-14

在这种情况下,您试图模仿实用程序类上的静态方法,这是Mockito所不允许的。请参见用Mockito模仿静态方法了解更多细节。

如果您试图测试的是数学的有效性,那么您可以简单地使用基本断言对它们进行单元测试。如果您想在测试中使用mock,您可以探索上面文章中建议的替代方案,或者重构代码以依赖非静态方法。

假设Function1只是传递给它的变量的保持器,对于每个要更改的内部类:

public static class MySin {
    public static double mySin(double x, double accuracy) throws Exception {
        return MyCos.myCos(Math.PI/2 - x, accuracy);
    }
}

public static class MySin {
    public double mySin(double x, double accuracy) throws Exception {
        return MyCos.myCos(Math.PI/2 - x, accuracy);
    }
}

请注意方法中移除的静态修饰符。

 类似资料:
  • 集成测试是对已经进行单元测试的各个部分的一种整合测试。集成是昂贵的,并且它出现在测试中。你必须把这个考虑到你的预计和时间表里。 理想情况下,你应该这样组织一个项目,使得最后没有一个阶段是必须通过显式集成来进行的。这比在项目过程中,随着事情完成逐渐集成事情要好得多。如果这是不可避免的,请仔细评估。

  • 我正在尝试使用测试驱动设计方法编写一个应用程序--我对单元测试很陌生,所以我只是想知道测试正确输入和异常的正确方法是什么。 我有一个用于加载配置文件的类: null 另外,这3个测试是否都有try{}catch(){}语句?在第一个测试中,正确性是隐含的,在第二个和第三个测试中,我无论如何都在检查异常,所以异常对测试没有影响。

  • 我正在尝试将Spring Boot应用程序的一些集成测试从迁移到。目前,测试使用的是 当测试运行时,被配置为使用与服务器运行时相同的基本URL和(随机选择的)端口。 在我的一个测试中,我登录并保存authorization-response头值,以便在后续的API调用中使用。我试着将它迁移到,就像这样 但是当我像这样创建实例时,它没有配置为使用与应用程序相同的端口。 我尝试使用的依赖注入实例 这确

  • Gradle4.6增加了对JUnit5的支持。 只要我没有用于例如集成测试的另一个sourceset,这对我是有效的:我不知道如何在我的集成测试中启用。 我所能做的是让任务与新的JUnit5支持一起工作,但我的任务使用JUnit5控制台并从命令行运行测试。最后,我在gradle中放弃对JUnit5的支持,并回滚到使用JUnit5控制台进行两个测试。 除了之外,如何在其他任务上启用Gradle4.6

  • 现在我们有一个项目,包含两个工作。1) 是带有单元测试的标准构建。2) 是集成测试。它们是这样工作的: 构建整个项目,运行单元测试,启动集成测试工作 问题是步骤2)现在需要一个多小时才能运行,我想将集成测试并行化,以便它们花费更少的时间。但我不确定我该怎么做。我的第一个想法是,我可以有两个这样的步骤: 构建整个项目,运行单元测试,启动集成测试工作 构建整个项目,将其部署到integration s

  • 下面是我试图作为POC开始的部分,它抛出异常: 我在以下得到以下例外: 是否有人可以帮助使用spring-data在elasticsearch中进行集成测试的任何其他选项,或者我应该如何为elasticsearch编写集成测试。 我知道在stackoverflow和embedded-elasticsearch的其他门户上还有其他的答案,但这些都不适合我当前的elasticsearch版本。