Mockito间谍与模拟:深入理解Mockito.spy()与Mockito.mock()
在单元测试的世界里,Mockito
是一个不可或缺的工具,它让测试变得更加简单和直观。本文将通过实际代码示例,详细探讨Mockito
中的spy()
与mock()
方法,以及它们在测试中的具体应用。
背景知识
在Java单元测试中,我们经常需要模拟对象的行为,以便在不依赖实际实现的情况下测试代码。Mockito
提供了两种主要的方式来创建模拟对象:spy()
和mock()
。
Mockito.mock()
Mockito.mock()
用于创建一个完全的模拟对象。使用此方法创建的对象,其所有方法调用都会返回默认值,或者根据我们的stubbing进行定制。
Mockito.spy()
与mock()
不同,spy()
方法创建的是一个部分模拟的对象。这意味着,除非我们明确地stub了某个方法,否则该方法将调用实际的实现。
示例项目
接下来,我将通过一个简单的计算器类MyCalc
来展示Mockito.spy()
与Mockito.mock()
的使用。
package com.logicbig.example;
public class MyCalc {
public int multiple(int x, int y) {
return x * y;
}
public int add(int x, int y) {
return x + y;
}
}
使用Mockito.spy()
首先,我们创建一个MyCalc
的spy实例,并测试其multiple
方法。
package com.logicbig.example;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;
public class MyCalcTest {
@Test
public void multiplyTest() {
MyCalc myCalcSpy = Mockito.spy(MyCalc.class);
int result = myCalcSpy.multiple(3, 2);
Assert.assertEquals(6, result); // 调用实际方法,预期结果为6
}
}
使用Mockito.mock()和thenCallRealMethod()
然后,我们创建一个MyCalc
的mock实例,并使用thenCallRealMethod()
来调用实际的multiple
方法。
package com.logicbig.example;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;
public class MyCalcTest2 {
@Test
public void multiplyTest() {
MyCalc myCalcMock = Mockito.mock(MyCalc.class);
Mockito.when(myCalcMock.multiple(3, 2)).thenCallRealMethod();
int result = myCalcMock.multiple(3, 2);
Assert.assertEquals(6, result); // 使用thenCallRealMethod调用实际方法
}
}
替换spy的方法
最后,我们展示如何通过stubbing来替换spy实例的方法行为。
package com.logicbig.example;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;
public class MyCalcTest3 {
@Test
public void multiplyTest() {
MyCalc myCalcSpy = Mockito.spy(MyCalc.class);
Mockito.when(myCalcSpy.add(3, 2)).thenReturn(100); // 替换add方法的行为
int result = myCalcSpy.multiple(3, 2);
Assert.assertEquals(6, result); // 调用实际的multiple方法
int result2 = myCalcSpy.add(3, 2);
Assert.assertEquals(100, result2); // 验证add方法被替换
}
}
结论
通过上述示例,我们可以看到Mockito.spy()
和Mockito.mock()
在单元测试中的不同应用场景。spy()
允许我们测试对象的部分行为,同时保持其他方法的实际实现;而mock()
则提供了一个完全可控的模拟环境。正确选择使用哪种方法,可以使我们的测试更加灵活和有效。
技术栈
mockito-core
3.5.15:Mockito核心API和实现。junit
4.13:JUnit单元测试框架。- JDK 8
- Maven 3.5.4
希望本文能帮助你更好地理解Mockito
中的spy()
和mock()
方法,以及如何在实际项目中应用它们进行有效的单元测试。