【问题标题】:TestNG + Mockito + PowerMock - verifyStatic() does not workTestNG + Mockito + PowerMock - verifyStatic() 不起作用
【发布时间】:2016-03-04 16:48:02
【问题描述】:

我是新的 TestNG 和一般的单元测试。我将 TestNG 6.9.6 与 Mockito 1.10.19 和 PowerMock 1.6.4 一起使用。我想验证MyService 类中的myMethod() 方法是否在内部使用正确的参数调用静态方法Util.myStaticMethod。由于 Mockito 本身不支持对静态方法的验证,因此我将 PowerMock 与它一起使用。我的测试类如下所示:

public class MyTest
{
    private MyService myService;

    @Captor ArgumentCaptor<String> argCaptor;

    @BeforeMethod
    public void setup()
    {
        MockitoAnnotations.initMocks( this );
        myService = new MyService();
    }

    @Test
    @PrepareForTest(MyService.class)
    public void myTest()
    {
        PowerMockito.mockStatic(Util.class);
        myService.myMethod("arg");

        PowerMockito.verifyStatic(10);
        Util.myStaticMethod(anyString());
    }
}

这个测试预计会失败,因为myMethod 只调用了一次静态方法Util.myStaticMethod()。但是当我运行测试时,它总是通过,无论我将什么值传递给PowerMockito.verifyStatic()

另外,如果我在这个类中编写另一个测试方法然后运行测试,我会得到以下错误

org.mockito.exceptions.misusing.UnfinishedVerificationException: 
Missing method call for verify(mock) here:
-> at mypackage.MyTest.myTest(MyTest.java:21)

Example of correct verification:
    verify(mock).doSomething()

Also, this error might show up because you verify either of: final/private/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.
Mocking methods declared on non-public parent classes is not supported.

    at mypackage.MyTest.myTest.setup(MyTest.java:10)


Results :

Failed tests: 
  MyTest.setup:10 UnfinishedVerification 
Missing method call for ver...

Tests run: 3, Failures: 1, Errors: 0, Skipped: 1

它在verifyStatic() 方法上失败了,这让我认为 verifyStatic() 方法需要更多我没有提供的东西。此外,它表示测试总数为 3,而在这种情况下,我只有两种测试方法。

任何帮助将不胜感激。

编辑:按照建议,我尝试将MyUtil 类放在@PrepareForTest 注释中,它仍然给出相同的错误。

【问题讨论】:

    标签: java unit-testing mockito testng powermock


    【解决方案1】:

    好的,我认为这是非常特定于 TestNG 配置的,因为所有 JUnit 示例都是“开箱即用”的!

    阅读来自 PowerMock GitHub 站点的this 链接,该链接描述了有关如何将 TestNG 与 PowerMock 一起使用的更多详细信息。使用此示例代码在此处描述了您验证对模拟 static 方法的调用的场景:

    @PrepareForTest(IdGenerator.class)
    public class MyTestClass {
    
       @Test
       public void demoStaticMethodMocking() throws Exception {
          mockStatic(IdGenerator.class);
          when(IdGenerator.generateNewId()).thenReturn(2L);       
          new ClassUnderTest().methodToTest();
    
          // Optionally verify that the static method was actually called
          verifyStatic();
          IdGenerator.generateNewId();
       }
    
    }
    

    然后是这个信息块:

    为此,您需要告诉 TestNG 使用 PowerMock 对象工厂

    这是使用 TestNG XML 配置或在测试代码本身中完成的。为了完整起见,我已将上述 URL 中给出的选项复制到下方。 FWIW 我扩展了PowerMockTestCase,验证工作如您所愿。

    最后,不要忘记 @PrepareForTest 正确的类 - 即包含要模拟的 static 方法的类,正如 @Bax 指出的 here

    作为进一步的提示(您可能已经知道,但无论如何值得在这里提及)因为您没有使用 Mockito 来模拟对象,所以可以安全地删除 MockitoAnnotations.initMocks(this)

    完成所有这些工作后,您可能还想考虑使用 Powermock 等'Black Magic' 工具是否实际上在您的设计中暴露了code smells?特别是因为看起来包含 static 方法的类在您的所有权之下。这意味着您可以使用不使用statics 的替代设计。我强烈推荐 Michael Feathers 的书 Working Effectively with Legacy Code,它可能会改变你的整个软件设计和测试方法......

    祝你好运!

    配置 TestNG 以使用 PowerMock 对象工厂

    使用套件.xml

    在您的 suite.xml 中,在套件标签中添加以下内容: object-factory="org.powermock.modules.testng.PowerMockObjectFactory" 例如

    <suite name="dgf" verbose="10"
        object-factory="org.powermock.modules.testng.PowerMockObjectFactory">
        <test name="dgf">
            <classes>
                <class name="com.mycompany.Test1"/>
                <class name="com.mycompany.Test2"/>
            </classes>
        </test> 
    

    如果您使用的是 Maven,您可能需要向 Surefire 指出该文件:

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <configuration>
            <suiteXmlFiles>
            <suiteXmlFile>suite.xml</suiteXmlFile>
            </suiteXmlFiles>
        </configuration> 
    </plugin> 
    

    以编程方式

    将这样的方法添加到您的测试类中:

    @ObjectFactory public IObjectFactory getObjectFactory() {
         return new org.powermock.modules.testng.PowerMockObjectFactory(); 
    } 
    

    或者为了安全起见,您也可以从PowerMockTestCase 扩展:

    @PrepareForTest(IdGenerator.class) 
    public class MyTestClass extends PowerMockTestCase { ... }
    

    【讨论】:

    • 我的错。我跳过了 xml 配置部分,因为我虽然肯定会处理它。这解决了这个问题。还将考虑改进设计,它确实是遗留代码!感谢您的建议。
    • 这个答案在 2020 年很有帮助!今天,我确认使用 TestNG 7.1.0、Mockito 3.6.28、PowerMock 2.0.9:需要extends PowerMockTestCase。我不需要getObjectFactory
    【解决方案2】:

    由于此页面在搜索结果中的排名很高,我只想在斯蒂芬已经写过的有用文档中添加更多内容。在最初遇到一些问题后,我刚刚成功地将 JUnit 测试用例迁移到了 TestNG。我发现你可以做suite.xml mods,或者“以编程方式”做,但没有必要两者都做。

    对于以编程方式执行此操作,@ObjectFactory 方法对我不起作用,但子类化 PowerMockTestCase 可以。这是我的示例代码:

    import org.mockito.Mockito;
    import org.powermock.api.mockito.PowerMockito;
    import org.powermock.core.classloader.annotations.PrepareForTest;
    import org.powermock.modules.testng.PowerMockTestCase;
    import org.testng.annotations.Test;
    
    @PrepareForTest(Pokeball.class)
    public class PokeballTestTestNG extends PowerMockTestCase {
    // Did not work for me
    // @ObjectFactory
    //    public IObjectFactory getObjectFactory() {
    //        return new org.powermock.modules.testng.PowerMockObjectFactory();
    //    }
    
        @Test
        public void test1() throws Exception {
            PowerMockito.spy(Pokeball.class);
    
            Pokeball.getNetworkMessage();
            Pokeball.getNetworkMessageLang(42);
            Pokeball.getNetworkMessageLang(42);
    
            PowerMockito.verifyStatic(); //verify one time invocation (default), passes
    //        PowerMockito.verifyStatic(Mockito.times(11)); //fails
            Pokeball.getNetworkMessage(); //need to call the method per PowerMock operation - actual test is done here - Exception thrown here upon failure
    
            PowerMockito.verifyStatic(Mockito.times(2));
            Pokeball.getNetworkMessageLang(42);
        }
    }
    

    编辑:pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>myG</groupId>
        <artifactId>myTestDouble</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <properties>
            <powermock.version>1.7.0</powermock.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.mockito</groupId>
                <artifactId>mockito-core</artifactId>
                <version>2.8.9</version>
                <scope>test</scope>
            </dependency>
    
            <!--JUnit-->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.12</version>
                <scope>test</scope>
            </dependency>
    
            <!--JUnit-->
            <dependency>
                <groupId>org.powermock</groupId>
                <artifactId>powermock-module-junit4</artifactId>
                <version>${powermock.version}</version>
                <scope>test</scope>
            </dependency>
    
            <!--TestNG-->
            <dependency>
                <groupId>org.powermock</groupId>
                <artifactId>powermock-module-testng</artifactId>
                <version>${powermock.version}</version>
                <scope>test</scope>
            </dependency>
    
            <!--Both TestNG & JUnit-->
            <dependency>
                <groupId>org.powermock</groupId>
                <artifactId>powermock-api-mockito2</artifactId>
                <version>${powermock.version}</version>
                <scope>test</scope>
            </dependency>
    
        </dependencies>
    </project>
    

    【讨论】:

    • 您能否告诉您为 PowerMockito 正常工作添加了哪些 maven 依赖项?我收到以下类的错误:import org.powermock.modules.testng.PowerMockTestCase;
    • @saint1729 我已经添加了 pom.xml。我想你可能不需要对那里的所有依赖。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多