如何使用Mockito与Spock测试Feature Toggle功能开关
解决方案
你遇到的测试失败是正常现象:当checksLoginAndRegistration=false时,代码不会进入service.validateRegistration的调用分支,自然不会抛出你预期的AccountBlockedException。对于Feature Toggle的测试,补充现有测试、单独编写用例两种方案都可行,更推荐后者保证测试逻辑的单一清晰。
方案1:独立编写两类测试用例(推荐)
为开关的两种状态分别写测试,逻辑直观易维护:
- 开关开启场景:保留你原有测试的逻辑,显式指定配置
feature.toggles.checksLoginAndRegistration=true,验证异常抛出、validateRegistration被调用 - 开关关闭场景:显式指定配置
feature.toggles.checksLoginAndRegistration=false,验证无异常抛出、validateRegistration未被调用
Spock测试示例(用ReflectionTestUtils直接赋值更轻量,无需加载全量Spring上下文)
def "开关开启时,注册校验不通过抛出账户锁定异常"() { given: "设置开关为开启状态" ReflectionTestUtils.setField(repository, "checksLoginAndRegistration", true) and: "mock validateRegistration抛出异常" 1 * service.validateRegistration(_) >> { throw new AccountBlockedException(user.username) } // 其他依赖mock逻辑和原有测试保持一致即可 when: "调用创建用户方法" repository.create(registrationData, anonymousInfo, "https://test") then: "捕获到预期异常" thrown(AccountBlockedException) } def "开关关闭时,跳过注册校验不抛出异常"() { given: "设置开关为关闭状态" ReflectionTestUtils.setField(repository, "checksLoginAndRegistration", false) and: "校验方法不会被调用" 0 * service.validateRegistration(_) // 其他依赖mock逻辑和原有测试保持一致即可 when: "调用创建用户方法" def result = repository.create(registrationData, anonymousInfo, "https://test") then: "方法执行成功无异常" noExceptionThrown() result != null }
方案2:参数化测试合并场景
如果希望减少重复代码,可以用Spock的参数化能力把两种场景合并为同一个测试方法:
def "开关状态为#toggleStatus时,注册校验逻辑符合预期"() { given: "设置开关状态为${toggleStatus}" ReflectionTestUtils.setField(repository, "checksLoginAndRegistration", toggleStatus) and: "mock对应依赖" invokeTimes * service.validateRegistration(_) >> { if(invokeTimes == 1) throw new AccountBlockedException(user.username) } // 其他依赖mock逻辑和原有测试保持一致即可 when: "调用创建用户方法" repository.create(registrationData, anonymousInfo, "https://test") then: "结果符合预期" expectedException == null ? noExceptionThrown() : thrown(expectedException) where: toggleStatus | invokeTimes | expectedException true | 1 | AccountBlockedException false | 0 | null }
注意要点
无论用哪种方案,都要同时验证两个点:
- 对应分支的业务逻辑执行结果符合预期
- 未命中的分支对应的依赖方法确实没有被调用,避免出现开关不生效的隐藏问题
内容的提问来源于stack exchange,提问作者user9347049
相关产品推荐
相关产品推荐

