[Java学习]Java Maven项目学习Powermock的mock和spy的区别

针对如下代码进行单元测试编写:

package com.example.learn.privateMock;

public class EmployeeService {
    
    

    public boolean exist(String userName) {
    
    
        checkExist(userName);
        return true;
    }

    private void  checkExist(String name) {
    
    
        throw new UnsupportedOperationException();
    }
}

困难点是checkExist(String name)方法被private修饰,不能使用junit进行测试。
只能使用PowerMock框架进行测试
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>org.example</groupId>
    <artifactId>LearnJavaDemo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <properties>
        <java.version>1.8</java.version>
        <jacoco.version>0.8.5</jacoco.version>
        <powermock.version>2.0.7</powermock.version>
        <maven.compiler.source>${java.version}</maven.compiler.source>
        <maven.compiler.target>${java.version}</maven.compiler.target>
        <jacoco.it.execution.data.file>${project.build.directory}/coverage-reports/jacoco-it.exec
        </jacoco.it.execution.data.file>
        <jacoco.ut.execution.data.file>${project.build.directory}/coverage-reports/jacoco-ut.exec
        </jacoco.ut.execution.data.file>
        <jdk.version>1.8</jdk.version>
        <!--项目版本 -->
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.powermock</groupId>
            <artifactId>powermock-module-junit4</artifactId>
            <version>${powermock.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.powermock</groupId>
            <artifactId>powermock-api-mockito2</artifactId>
            <version>${powermock.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.jacoco</groupId>
            <artifactId>jacoco-maven-plugin</artifactId>
            <version>${jacoco.version}</version>
        </dependency>
        <dependency>
            <groupId>org.jacoco</groupId>
            <artifactId>org.jacoco.agent</artifactId>
            <version>${jacoco.version}</version>
            <classifier>runtime</classifier>
        </dependency>
    </dependencies>
    <build>
        <finalName>${project.name}</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>${jdk.version}</source>
                    <target>${jdk.version}</target>
                    <encoding>${project.build.sourceEncoding}</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.jacoco</groupId>
                <artifactId>jacoco-maven-plugin</artifactId>
                <version>${jacoco.version}</version>
                <executions>
                    <execution>
                        <id>default-instrument</id>
                        <goals>
                            <goal>instrument</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>default-restore-instrumented-classes</id>
                        <goals>
                            <goal>restore-instrumented-classes</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>report</id>
                        <phase>prepare-package</phase>
                        <goals>
                            <goal>report</goal>
                        </goals>
                        <configuration>
                            <dataFile>${project.build.directory}/coverage.exec</dataFile>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.19.1</version>
                <configuration>
                    <systemPropertyVariables>
                        <jacoco-agent.destfile>${project.build.directory}/coverage.exec</jacoco-agent.destfile>
                    </systemPropertyVariables>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

单元测试用例代码如下:

package com.example.learn.privateMock;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.Whitebox;

@RunWith(PowerMockRunner.class)
@PrepareForTest({
    
    EmployeeService.class})
public class EmployeeServiceTest {
    
    

    private final String userName = "zhangsan";
    
    @Test
    public void testSpyCheckExist() throws Exception {
    
    
        // 通过.spy出的对象,调用自己的exist(userName)方法时,就会执行真的checkExist(String name)方法
        EmployeeService service = PowerMockito.spy(new EmployeeService());
        PowerMockito.doNothing().when(service,"checkExist", userName);
        Assert.assertTrue(service.exist(userName));
        PowerMockito.verifyPrivate(service,Mockito.times(1)).invoke("checkExist", userName);
    }

    @Test
    public void testMockCheckExist() throws Exception {
    
    
        EmployeeService service = PowerMockito.mock(EmployeeService.class);
        PowerMockito.doNothing().when(service,"checkExist", userName);
        /**
         * 通过.mock出的对象,调用它自己的exist(userName)方法时,实际上调用的是exist(userName){}空方法,
         * exist方法里面的逻辑并没有执行checkExist(String name),
         * 而通过.spy出的对象,调用自己的exist(userName)方法时,就会执行真的checkExist(String name)方法
         */
        service.exist(userName);
        PowerMockito.verifyPrivate(service, Mockito.never()).invoke("checkExist", userName);
    }

    @Test
    public void testCheckExistThrowExcept(){
    
    
        try {
    
    
            // 通过.spy出的对象,调用自己的exist(userName)方法时,就会执行真的checkExist(String name)方法
            EmployeeService service = PowerMockito.spy(new EmployeeService());
            service.exist(userName);
            PowerMockito.verifyPrivate(service).invoke("checkExist", userName);
        } catch (Exception e) {
    
    
            Assert.assertTrue(e instanceof UnsupportedOperationException);
        }
    }

    @Test
    public void testCheckExistThrowExcept2(){
    
    
        try {
    
    
            // 通过.spy出的对象,调用自己的exist(userName)方法时,就会执行真的checkExist(String name)方法
            EmployeeService service = PowerMockito.spy(new EmployeeService());
            Whitebox.invokeMethod(service, "checkExist", userName);
            PowerMockito.verifyPrivate(service).invoke("checkExist", userName);
        } catch (Exception e) {
    
    
            Assert.assertTrue(e instanceof UnsupportedOperationException);
        }
    }
}

使用命令行执行单元测试,并生成覆盖率:

mvn clean install

稍等片刻,在项目根目录下,target/site/jacoco/index.html生成覆盖率报告
覆盖率报告概述截图
覆盖率报告详情

猜你喜欢

转载自blog.csdn.net/weixin_45329445/article/details/109563731