Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Jmockit:如何验证在特定实例上调用了方法_Java_Unit Testing_Jmockit - Fatal编程技术网

Java Jmockit:如何验证在特定实例上调用了方法

Java Jmockit:如何验证在特定实例上调用了方法,java,unit-testing,jmockit,Java,Unit Testing,Jmockit,我正在Java1.7上使用JMockit1.15 我想验证一些经过测试的代码是否先创建一个特定类(ExampleClass)的新实例,然后在该实例上调用一个方法。 我尝试了很多方法,使用了验证、期望、模拟、注射等多种不同的方法,但都没有成功 下面是一个例子 示例类是一个类;我将模拟它,我想验证它是如何使用的 public class ExampleClass { final double id = Math.random(); public ExampleClass() {

我正在Java1.7上使用JMockit1.15

我想验证一些经过测试的代码是否先创建一个特定类(ExampleClass)的新实例,然后在该实例上调用一个方法。 我尝试了很多方法,使用了验证、期望、模拟、注射等多种不同的方法,但都没有成功

下面是一个例子

示例类是一个类;我将模拟它,我想验证它是如何使用的

public class ExampleClass {

    final double id = Math.random();

    public ExampleClass() {
    }

    public void doSomething() {
        System.out.println("I did something - " + id);
    }

}
ExampleClassUser包含我要测试的逻辑

请注意,ErrorUsage()生成ExampleClass的两个实例,但总是在第一个实例上调用doSomething()

public class ExampleClassUser {

    public void rightUsage() {
        final ExampleClass exampleClass1 = new ExampleClass();
        exampleClass1.doSomething();

        final ExampleClass exampleClass2 = new ExampleClass();
        exampleClass2.doSomething();
    }

    public void wrongUsage() {
        final ExampleClass exampleClass1 = new ExampleClass();
        exampleClass1.doSomething();

        final ExampleClass exampleClass2 = new ExampleClass();
        exampleClass1.doSomething();
    }

}
示例ClassUserTest是我想要构建的测试。 它应该检查对rightUsage()或ErrorUsage()的每个方法调用

  • 创建ExampleClass的新实例
  • 对该实例调用doSomething
  • 创建ExampleClass的另一个实例
  • 在第二个实例中调用doSomething
  • 当应用于rightUsage()时,测试应该成功,而当应用于ErrorUsage()时,测试应该失败

    当然,我的测试无法做到这一点,因为它只检查是否正在创建新实例以及是否执行了两个方法调用,但**不检查在哪个实例上执行了方法调用”


    测试实例化对象的方法有点困难,因为在方法之外,您无法访问新创建的实例。解决方法是使用
    工厂
    创建
    ExampleClass
    实例,并将其作为依赖项传递给
    ExampleClassUser
    。现在您使用的是c控制,因为您可以模拟工厂以返回您需要的任何对象(模拟、自定义单元测试对象等),并且由于您可以访问这些对象,因此可以对它们进行断言

    另一种方法是,如果您不强烈需要确保调用了对象/方法,则不断言调用了正确的对象/方法,而是断言这些调用的效果。这将有利于将测试与方法实现分离。这种方法只有在
    doSomething()时才可行
    具有无需访问对象即可检测到的副作用,并且可能涉及复杂的设置


    例如,如果
    doSomething()
    返回一个素数,每次调用它都返回下一个素数(第一次调用将返回2,第二次调用将返回3,依此类推),并且测试的方法将两个数相加并返回它们(是的,我知道一个愚蠢的示例),那么您可以检测
    doSomething()对两个不同的对象调用了
    ,因为它们的总和是4。如果对同一个对象调用了
    doSomething()
    ,则返回的结果是5。

    对于JMockit 1.17或更高版本,以下版本的测试将起作用(即,它将按预期失败):


    你认为这是一个Jmockit限制还是一个糟糕的测试模式?这不是一个Jmockit限制,而是不可测试的代码。基本上,因为对创建对象的引用只能在封闭方法的范围内访问,所以从方法之外几乎无法完成。现在,如果你想测试doSomething()在适当的对象上调用,然后将对象实例化移到方法之外的某个地方(和jmockit)拥有访问权限,或者……我会将此方法添加到答案中,因为它对其他在该页面上运行的人会有帮助。测试可以用JMockit编写,但看起来不太好。我认为您应该描述您需要解决的实际测试问题,而不是展示一个人为的示例。我打赌真正的问题会更容易。嗯,我尝试了通过一个特别的示例,我将更清楚地说明它,并且它是可执行的,但是,正如您所要求的,我将报告真实的情况。我有一个表示ssh调用的类(使用构造函数
    SshCommand(String命令,Host targetHost)
    ),还有一个
    execute()
    method。这个类的许多实例在整个测试代码中都被使用。我希望我的单元测试能够检查哪些实例被创建,哪些实例上使用了
    execute()
    方法。我在下面看到了您的示例解决方案,这正是我所想的(我只需要等待新版本发布)。您为什么说“它看起来不好?在JMockit 1.16或更老版本上它看起来不好,因为测试必须使用带有
    调用
    参数的
    委托
    对象,这样它才能访问新实例并将其保存到测试类中的字段中。JMockit 1.17+使用内部“等效实例”“将方法期望值与以前匹配的构造函数期望值匹配时进行映射,这样测试就简单多了。您认为在验证块中内联编写对象创建和方法调用(
    new ExampleClass().doSomething();
    )而不是将新创建的实例分配给变量是一样的吗?”?(这似乎有效,但我不太确定它是否正确);为了清楚起见,我只使用了局部变量。
    import mockit.FullVerificationsInOrder;
    import mockit.Mocked;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    
    
    @RunWith(mockit.integration.junit4.JMockit.class)
    public class ExampleClassUserTest {
    
        @Test
        public void testUsage(final @Mocked ExampleClass exampleClass) {
    
            //new ExampleClassUser().rightUsage();
            new ExampleClassUser().wrongUsage();
    
            new FullVerificationsInOrder() {{
                new ExampleClass();
                exampleClass.doSomething();
    
                new ExampleClass();
                exampleClass.doSomething();
            }};
    
        }
    
    }
    
    @Test
    public void testUsage(@Mocked ExampleClass exampleClass)
    {
        new ExampleClassUser().wrongUsage();
    
        new FullVerificationsInOrder() {{
            ExampleClass e1 = new ExampleClass(); // matches first new instance
            e1.doSomething(); // matches only on instances equivalent to "e1"
    
            // Same as before, now for the second instance.
            ExampleClass e2 = new ExampleClass();
            e2.doSomething(); // fails with a "missing invocation"
        }};
    }