Scala单元测试如何使用Mockito创建Mock API模拟外部依赖
单元测试Mock otherTeamAPI 实现方案
现有业务代码
def getData(host:String, port:Int, date: String): Map[String, String] = { val data = new otherTeamAPI(host,port) val latestData = data.getLatestData(date) }
常见疑问解答
1. 直接写val otherTeamAPI = Mock[otherTeamAPI]能不能生效?
不能。你现在的getData方法是在函数内部直接通过new关键字实例化真实的otherTeamAPI对象,外部创建的Mock实例根本不会被函数内部用到,打桩逻辑完全不生效。
2. 正确的Mock实现步骤
首先要调整代码的依赖写法,不要在业务逻辑里硬编码实例化外部依赖,推荐用依赖注入的方式改造,两种常用写法:
- 方法参数注入:把API实例作为参数传入
getData
def getData(api: otherTeamAPI, date: String): Map[String, String] = { api.getLatestData(date) }
- 构造器注入:把
otherTeamAPI作为业务类的成员变量,初始化业务类的时候传入实例,测试时直接传Mock对象即可。
改造完成后,Mockito的Mock写法如下(以Scala生态常用的mockito-scala + ScalaTest为例):
// 创建Mock实例 val mockApi = mock[otherTeamAPI] // 预设测试数据和打桩规则 val testDate = "2024-05-20" val expectData = Map("order_count" -> "123", "uv" -> "4567") // 约定当传入testDate调用getLatestData时,返回预设的测试数据 when(mockApi.getLatestData(testDate)).thenReturn(expectData)
3. 调用getData时怎么获取Mock的测试数据?
打桩完成后,把Mock实例传入改造后的getData方法执行即可,方法内部调用getLatestData时会自动返回你预设的测试数据,不需要额外获取。你还可以通过校验逻辑确认调用符合预期:
// 执行业务方法 val actualResult = getData(mockApi, testDate) // 断言返回值和预设测试数据一致 assert(actualResult == expectData) // 验证getLatestData方法确实被调用了1次,入参正确 verify(mockApi, times(1)).getLatestData(testDate)
4. 是否需要每次测试都新建Mock实例?
建议每个测试用例都使用全新的Mock实例。Mock对象会保存打桩规则、调用记录等状态,多测试用例复用同一个Mock实例很容易造成状态污染,导致测试结果不稳定。
如果觉得每次手动初始化麻烦,可以用测试框架的前置钩子自动完成初始化,示例:
class DataServiceTest extends AnyFunSuite with MockitoSugar with BeforeAndAfterEach { var mockApi: otherTeamAPI = _ val testDate = "2024-05-20" val expectData = Map("order_count" -> "123", "uv" -> "4567") override def beforeEach(): Unit = { // 每个用例执行前都新建全新的Mock实例 mockApi = mock[otherTeamAPI] } test("getData should return correct mocked data") { when(mockApi.getLatestData(testDate)).thenReturn(expectData) val res = getData(mockApi, testDate) assert(res == expectData) verify(mockApi, times(1)).getLatestData(testDate) } }
如果你暂时无法改造硬编码new实例的逻辑,可以用PowerMock模拟构造函数返回Mock实例,但这种方式会提升测试复杂度,长期来看还是推荐用依赖注入的写法提升代码可测试性。
内容的提问来源于stack exchange,提问作者Lapchi
相关产品推荐
相关产品推荐

