参数类
/**
* @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)
}
}
}
网友评论