mockito 尝试模拟具有静态方法的类的示例不起作用

2skhul33  于 2023-03-12  发布在  其他
关注(0)|答案(1)|浏览(272)

我正在尝试学习如何使用Mockito,特别是我正在尝试理解如何使用静态方法的模拟。我正在使用Eclipse作为IDE,我找到了这个页面:
https://www.testim.io/blog/mocking-static-methods-mockito/
并尝试测试“选项#1:创建 Package 器对象”。
因此,我已经根据那篇文章创建了类和接口,并添加了“mockito-extensions”目录和包含字符串的“mockito-extensions/org.mockito.plugins.MockMaker”文件,但随后我尝试在Eclipse中运行测试(Runas单元测试),它似乎正在执行“StringCalculatorTest”类中的代码,但它没有执行t看起来实际上进入了实现类和带有静态方法的原始类。
下面是使用static方法的类:

package mil.nga.geoaxis.orchestrator_spring.rest;

public class StringCalculatorStatic {
    
      public static int add(String numbers) {
          System.out.println("In StringCalculatorStatic: Entering...");
            String[] parts = numbers.split(",");
            int sum = 0;
            for (String part : parts) {
              int number = Integer.parseInt(part);
              sum += number;
            }
            System.out.println("In StringCalculatorStatic: sum=[" + sum + "]");
            return sum;
      } // end add()

}

这是它的界面

package mil.nga.geoaxis.orchestrator_spring.rest;

public interface StringCalculator {
    
    public int add(String numbers);

}

和实现类:

package mil.nga.geoaxis.orchestrator_spring.rest;

public class StringCalculatorImpl implements StringCalculator{
    @Override
    public int add(String numbers) {
        System.out.println("In StringCalculatorImp.add: Entering...");
        return StringCalculatorStatic.add(numbers);
    }

}

最后是测试类:

package mil.nga.geoaxis.orchestrator_spring.rest;

import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.Mockito;

public class StringCalculatorTest {
    
    
    @Test
    public void testAdd() {
        System.out.println("In StringCalculatorTest.testAdd: Entering...");
        System.out.println("In StringCalculatorTest.testAdd: About to create the mock of StringCalculator object...");
        StringCalculator calc = Mockito.mock(StringCalculator.class);
        System.out.println("In StringCalculatorTest.testAdd: Created the mock of StringCalculator object and reference stored in 'calc'");

        System.out.println("In StringCalculatorTest.testAdd: About to call calc() method...");
        int responseFromCallingCalc = calc.add("4,6");
        System.out.println("In StringCalculatorTest.testAdd: Returned from calling calc() method, responseFromCallingCalc=[" + responseFromCallingCalc + "]");
        
        Mockito.when(calc.add("4,6")).thenReturn(10);
        System.out.println("In StringCalculatorTest.testAdd FINISHED...");
    }

}

当我执行RunAs Junit时,输出为:

In StringCalculatorTest.testAdd: Entering...
In StringCalculatorTest.testAdd: About to create the mock of StringCalculator object...
In StringCalculatorTest.testAdd: Created the mock of StringCalculator object and reference stored in 'calc'
In StringCalculatorTest.testAdd: About to call calc() method...
In StringCalculatorTest.testAdd: Returned from calling calc() method, responseFromCallingCalc=[0]
In StringCalculatorTest.testAdd FINISHED...

其他类的输出都没有出现,所以我猜,出于某种原因,它实际上并没有执行模拟操作?
有人能帮助/建议我错过了什么吗?
谢谢你,吉姆
编辑:我已经编辑了测试类,添加了对“calc”的调用(根据Lesiak的建议,还有一些额外的调试printlns),但看起来它仍然只执行测试类代码,而不执行StringCalculatorStatic类中的静态方法。

6jygbczu

6jygbczu1#

我找到了这个页面https://www.testim.io/blog/mocking-static-methods-mockito/并尝试测试“选项#1:创建 Package 器对象”。
从该页备选案文1(着重号为我)
第一个选项包括根本不模拟静态方法
所以...
其他类的输出都没有出现,所以我猜,出于某种原因,它实际上并没有执行模拟操作?
有人能帮助/建议我错过了什么吗?
你忽略了一个事实,那就是你所读的文章建议你不要模拟静态对象。它的工作方式完全符合预期。你创建一个 Package 类,而不是模拟一个静态函数。然后在测试中模拟 Package 类的示例,而不是模拟静态函数。
编辑:后续问题。
但我想我是在按你说的做?
是的,你是。这就是问题的关键。你正在创建一个静态的 Package 器,而从来没有实际使用或模拟静态函数。
StringCalculatorImpl是StringCalculator接口的实现,在StringCalculatorTest中,我做了“StringCalculator calc = Mockito.mock(StringCalculator.class)",即创建StringCalculator类的一个模拟示例,这不正是文章(以及您的建议(“然后在您的测试中模拟 Package 器类的示例,而不是模拟静态函数”)吗?
是的。回到你最初的问题:
其他类的输出都没有出现,所以我猜,出于某种原因,它实际上并没有执行模拟操作?
根据您的问题和随后的回答,我认为您对模拟的工作原理有误解。您看不到其他类的输出 *,正是因为它正在进行模拟 *。
让我们回顾一下:

StringCalculator calc = Mockito.mock(StringCalculator.class);

这是一个你定义的接口的模拟,它去掉了不做任何事情的方法,因此,你在StringCalculatorImpl中的 * 真实的 * add方法永远不会被调用,当你这样做的时候,你永远不会看到print语句:

int responseFromCallingCalc = calc.add("4,6");

而且,因为您没有告诉Mockito在那个mock上调用那个方法时要做什么,所以您将得到一个默认值(0)。
接下来,您指示Mockito在给定特定输入的情况下返回一个特定值,然而,在此之后您没有对这个mock做任何其他操作,因此这个mock在您的示例中是没有意义的:

Mockito.when(calc.add("4,6")).thenReturn(10);

此时,如果您要获取calc.add("4,6")的值,它将返回10,正如您告诉它的那样。同样,- * 没有执行任何实际代码,因为您使用的是mock*。
如果这一点仍然不清楚,那么我最好的建议将是谷歌周围的教程或例子如何Mockito工作和阅读。

相关问题