美文网首页
PowerMockit 模拟测试方法内实例的对象

PowerMockit 模拟测试方法内实例的对象

作者: azu_test | 来源:发表于2023-02-17 10:42 被阅读0次

参数类

/**
 * @author azu
 * */
class EatInfo {
    var food: String? = null
    var address: String? = null
}

实例的对象Student

/**
 * @author azu
 * */
open class Student {
    var name: String? = null
    var age = 0

    constructor() {}
    constructor(name: String?) {
        this.name = name
    }

    constructor(name: String?, age: Int) {
        this.name = name
        this.age = age
    }

    open fun eatByOpenMethod(eatInfo: EatInfo) {
        println("go to" + eatInfo?.address + " to eat " + eatInfo?.food)
    }

    final fun eatByFinalMethod(eatInfo: EatInfo) {
        println("go to" + eatInfo?.address + " to eat " + eatInfo?.food)
    }
}

Java静态方法实例化Student对象

/**
 * @author azu
 */
public class StudentProductJava extends Student {
    private StudentProductJava() {

    }

    public static StudentProductJava getInstance() {
        return new StudentProductJava();
    }
}

Kotlin伴生对象实例化Student对象

/**
 * @author zau
 * */
class StudentProductKotlin1 {
    companion object {
        fun getInstance(): Student {
            return Student()
        }
    }
}

Kotlin Object对象实例化Student对象

/**
 * @author zau
 * */
object StudentProductKotlin2 {
    fun getInstance(): Student {
        return Student()
    }
}

需要做单元测试的类

/**
 * @author azu
 * */
class StudentManager {

    /**
     * 传参为实体对象时的处理
     * */
    fun getStudentInfo(student: Student): String {
        when (student.age) {
            6 -> {
                return "一年级: ${student.name}"
            }
            7 -> {
                return "二年级: ${student.name}"
            }
            8 -> {
                return "三年级: ${student.name}"
            }
            9 -> {
                return "四年级: ${student.name}"
            }
            10 -> {
                return "五年级: ${student.name}"
            }
            11 -> {
                return "六年级: ${student.name}"
            }
            else -> {
                return "未知: ${student.name}"
            }
        }
    }

    /**
     * 接口内实例化对象接口
     * */
    fun getStudentInfo(): String {
        val student = Student()
        return getStudentInfo(student)
    }

    /**
     * java 静态方法实例化对象
     * */
    fun getStudentInfoByJavaProduct(): String {
        val student = StudentProductJava.getInstance()
        return getStudentInfo(student as Student)
    }

    /**
     * kotlin 类内object方法生成实例对象
     * */
    fun getStudentInfoByKotlinProduct1(): String {
        val student = StudentProductKotlin1.getInstance()
        return getStudentInfo(student)
    }

    /**
     * kotlin object类内方法生成实例对象
     * */
    fun getStudentInfoByKotlinProduct2(): String {
        val student = StudentProductKotlin2.getInstance()
        return getStudentInfo(student)
    }

    /**
     * 非final方法参数捕获
     * */
    fun eatFoolOpen(student: Student) {
        val eatInfo = EatInfo()
        eatInfo.food = "香蕉"
        eatInfo.address = "教室"
        student.eatByOpenMethod(eatInfo)
    }

    /**
     * final方法参数捕获
     * */
    fun eatFoolFinal(student: Student) {
        val eatInfo = EatInfo()
        eatInfo.food = "苹果"
        eatInfo.address = "餐厅"
        student.eatByFinalMethod(eatInfo)
    }
}

PowerMockit依赖

    //mockito
    testImplementation "org.mockito:mockito-core:2.23.4"
    //powermock
    testImplementation "org.powermock:powermock-module-junit4:2.0.2"
    testImplementation "org.powermock:powermock-api-mockito2:2.0.2"
    testImplementation "org.powermock:powermock-classloading-xstream:2.0.2"
    testImplementation "org.powermock:powermock-module-junit4-rule:2.0.2"
    testImplementation 'org.mockito.kotlin:mockito-kotlin:3.2.0'

单元测试类

/**
 * @author azu
 */
@RunWith(PowerMockRunner::class)
@PrepareForTest(
    Student::class, StudentManager::class,
    StudentProductJava::class, StudentProductKotlin1::class,
    StudentProductKotlin2::class
)
class StudentManagerTest {

    @Captor
    private lateinit var eatInfoAc: ArgumentCaptor<EatInfo>
    private lateinit var studentManager: StudentManager

    @Before
    fun setUp() {
        studentManager = StudentManager()
    }

    /**
     * 直接使用真正对象测试
     * test: getStudentInfo(Student)
     * */
    @Test
    fun getStudentInfoTest1() {
        val student1 = Student("张三", 6)
        assertEquals("一年级: 张三", studentManager.getStudentInfo(student1))

        val student2 = Student("李四", 7)
        studentManager.getStudentInfo(student2)
        assertEquals("二年级: 李四", studentManager.getStudentInfo(student2))

        val student3 = Student("王五", 8)
        studentManager.getStudentInfo(student3)
        assertEquals("三年级: 王五", studentManager.getStudentInfo(student3))

        val student4 = Student("马六", 9)
        studentManager.getStudentInfo(student4)
        assertEquals("四年级: 马六", studentManager.getStudentInfo(student4))

        val student5 = Student("刘七", 10)
        studentManager.getStudentInfo(student5)
        assertEquals("五年级: 刘七", studentManager.getStudentInfo(student5))

        val student6 = Student("吴八", 11)
        studentManager.getStudentInfo(student6)
        assertEquals("六年级: 吴八", studentManager.getStudentInfo(student6))

        val student7 = Student("赵九", 12)
        studentManager.getStudentInfo(student7)
        assertEquals("未知: 赵九", studentManager.getStudentInfo(student7))
    }

    /**
     * mock学生对象
     * test: getStudentInfo(Student)
     * 前提条件:
     * @RunWith(PowerMockRunner::class) @PrepareForTest(Student::class, StudentManager::class)
     * */
    @Test
    fun getStudentInfoTest2() {
        //mock对象
        val student = PowerMockito.mock(Student::class.java)

        //mock对象的方法返回值设置
        PowerMockito.`when`(student.age).thenReturn(6)
        PowerMockito.`when`(student.name).thenReturn("张三")
        assertEquals("一年级: 张三", studentManager.getStudentInfo(student))

        //mock对象的方法返回值设置
        PowerMockito.`when`(student.age).thenReturn(7)
        PowerMockito.`when`(student.name).thenReturn("李四")
        assertEquals("二年级: 李四", studentManager.getStudentInfo(student))
    }

    /**
     * mock接口内普通实例化的对象
     * test: getStudentInfo()
     * */
    @Test
    fun getStudentInfo2Test() {
        //mock对象
        val student = PowerMockito.mock(Student::class.java)
        //声明方法内实例化对象时使用前面mock的对象
        PowerMockito.whenNew(Student::class.java).withNoArguments().thenReturn(student)
        //测试一
        //mock对象的方法返回值设置
        PowerMockito.`when`(student.age).thenReturn(6)
        //mock对象的方法返回值设置
        PowerMockito.`when`(student.name).thenReturn("张三")
        assertEquals("一年级: 张三", studentManager.getStudentInfo())
        //测试二
        //mock对象的方法返回值设置
        PowerMockito.`when`(student.age).thenReturn(7)
        //mock对象的方法返回值设置
        PowerMockito.`when`(student.name).thenReturn("李四")
        assertEquals("二年级: 李四", studentManager.getStudentInfo())

        //错误示例: 替换接口内的对象时不能用外部实例化的对象,只可使用mock的对象
        /*val student1 = Student("张三", 6)
        PowerMockito.whenNew(Student::class.java).withNoArguments().thenReturn(student1)
        assertEquals("一年级: 张三", studentManager.getStudentInfo2())*/
    }

    /**
     * mock接口内java静态方法实例化的对象
     * test: getStudentInfoByJavaProduct()
     * */
    @Test
    fun getStudentInfoByJavaProductTest() {
        PowerMockito.mockStatic(StudentProductJava::class.java)
        val student = PowerMockito.mock(StudentProductJava::class.java)
        PowerMockito.`when`(StudentProductJava.getInstance()).thenReturn(student)
        //测试一
        //mock对象的方法返回值设置
        PowerMockito.`when`(student.age).thenReturn(6)
        //mock对象的方法返回值设置
        PowerMockito.`when`(student.name).thenReturn("张三")
        assertEquals("一年级: 张三", studentManager.getStudentInfoByJavaProduct())
    }

    /**
     * mock 对象内object接口方法实例化的对象
     * test: getStudentInfoByKotlinProduct1()
     * */
    @Test
    fun getStudentInfoByKotlinProduct1Test() {
        val mockStudent = PowerMockito.mock(Student::class.java)
        //mock对象的方法返回值设置
        PowerMockito.`when`(mockStudent.age).thenReturn(10)
        //mock对象的方法返回值设置
        PowerMockito.`when`(mockStudent.name).thenReturn("刘七")

        PowerMockito.mockStatic(StudentProductKotlin1::class.java)
        val companionMock: StudentProductKotlin1.Companion = PowerMockito.mock(StudentProductKotlin1.Companion::class.java)
        Whitebox.setInternalState(
            StudentProductKotlin1::class.java, "Companion",
            companionMock
        )
        PowerMockito.`when`(companionMock.getInstance()).thenReturn(mockStudent)

        assertEquals("五年级: 刘七", studentManager.getStudentInfoByKotlinProduct1())
    }

    /**
     * mock object对象接口内静态方法实例化的对象
     * test: getStudentInfoByKotlinProduct2()
     * */
    @Test
    fun getStudentInfoByKotlinProduct2Test() {
        val mockStudent = PowerMockito.mock(Student::class.java)
        //mock对象的方法返回值设置
        PowerMockito.`when`(mockStudent.age).thenReturn(11)
        //mock对象的方法返回值设置
        PowerMockito.`when`(mockStudent.name).thenReturn("吴八")

        val mock = PowerMockito.mock(StudentProductKotlin2::class.java)
        //调用getInstance()时返回上面的mockStudent
        PowerMockito.`when`(mock.getInstance()).thenReturn(mockStudent)
        val declaredMethod = StudentProductKotlin2::class.java.getDeclaredField("INSTANCE")
        setFinalStatic(declaredMethod, mock)
        assertEquals("六年级: 吴八", studentManager.getStudentInfoByKotlinProduct2())
    }

    /**
     * 通过反射修改静态常量来mock普通的kotlin静态方法
     * */
    private fun setFinalStatic(field: Field, newValue: Any) {
        field.isAccessible = true
        val modifiersField: Field = Field::class.java.getDeclaredField("modifiers")
        modifiersField.isAccessible = true
        modifiersField.setInt(field, field.modifiers and Modifier.FINAL.inv())
        field.set(null, newValue)
    }


    /**
     * 参数捕获器
     * mock学生对象
     * test: eatFoolOpen()-> eatByOpenMethod()
     * 检查 mock对象非final方法的参数值
     * */
    @Test
    fun eatFoolOpenTest() {
        val student = PowerMockito.mock(Student::class.java)
        studentManager.eatFoolOpen(student)

        //方法1
        verify(student, times(1)).eatByOpenMethod(capture(eatInfoAc))
        assertEquals("香蕉", eatInfoAc.value.food)
        assertEquals("教室", eatInfoAc.value.address)

        //方法2
        argumentCaptor<EatInfo>().apply {
            verify(student, times(1)).eatByOpenMethod(this.capture())
            assertEquals(1, this.allValues.size)
            assertEquals("香蕉", this.firstValue.food)
            assertEquals("教室", this.firstValue.address)
        }
    }

    /**
     * 参数捕获器
     * mock学生对象
     * test: eatFoolFinal()-> eatByFinalMethod()
     * 检查 mock对象final方法的参数值
     * */
    @Test
    fun eatFoolFinalTest() {
        val student = PowerMockito.mock(Student::class.java)

        //方法1
        PowerMockito.`when`(student.eatByFinalMethod(capture(eatInfoAc))).then { }
        studentManager.eatFoolFinal(student)
        assertEquals("苹果", eatInfoAc.value.food)
        assertEquals("餐厅", eatInfoAc.value.address)

        //方法2
        argumentCaptor<EatInfo>().apply {
            PowerMockito.`when`(student.eatByFinalMethod(this.capture())).then { }
            studentManager.eatFoolFinal(student)
            assertEquals(1, this.allValues.size)
            assertEquals("苹果", this.firstValue.food)
            assertEquals("餐厅", this.firstValue.address)
        }
    }
}

相关文章

  • 类中的方法

    1.实例方法的调用方式 实例对象.实例方法() 类对象.实例方法(实例对象) 例如: class Student ...

  • 创建一个_new方法 -- p14-3-1

    说明: 创建一个_new方法模拟new实例==>目标:调用Dog其它类对象的方法 image.png 分析imag...

  • OC中的class方法

    实例对象的class方法 实例对象的class方法返回的是该实例对象的类对象 类对象的class方法 类对象的cl...

  • Go语言学习笔记 - 方法

    方法定义 方法总是绑定对象实例,并隐式将实例作为第一实参(receiver) 只能为当前包内命令类型定义方法。 参...

  • 类方法 VS 静态方法

    类对象、实例对象、类属性、实例属性、类方法、实例方法、静态方法。 @staticmethod@classmetho...

  • Swift 中的方法声明

    实例方法 类方法 静态方法 实例方法由实例对象进行调用;类方法和静态方法由类对象进行调用

  • Go方法(一)

    定义 方法是与对象实例绑定的特殊函数。方法是面向对象编程的基本概念,用于维护和展示对象的自身状态。对象是内敛的,每...

  • Android 使用 Intent 传递对象

    Serializable 方式: 实例代码: Parcelable 方式: 实例代码: 测试传递对象: 测试接收对...

  • 再论静态方法和类方法

    实例对象可以调用实例方法、类方法、静态方法 类对象只能调用类方法、静态方法

  • iOS 开发:类方法、对象方法

    Objective-C中的方法有两种:类方法和对象方法(也叫作实例方法)。 1、对象方法(实例方法) 1.1、对象...

网友评论

      本文标题:PowerMockit 模拟测试方法内实例的对象

      本文链接:https://www.haomeiwen.com/subject/bjvmkdtx.html