为何MockK无法验证Micronaut Meter计数器已递增?
Micrometer MeterRegistry无标签计数器测试失败原因及解决方法
问题背景
我需要测试代码是否正确更新了Micronaut(4.7.5)的指标,被测逻辑会接收MeterRegistry实例并调用其方法。测试代码如下:
import io.micrometer.core.instrument.Counter import io.micrometer.core.instrument.MeterRegistry import io.micrometer.core.instrument.Tag import io.micrometer.core.instrument.Tags import io.mockk.* import org.junit.jupiter.api.Test fun MeterRegistry.countIt(): Counter = counter("my-counter") fun MeterRegistry.countTagged(tag: String): Counter = counter("other-counter", Tags.of(Tag.of("tag", tag))) class RegistryTest { @Test fun `test counter`() { val registry: MeterRegistry = mockk(relaxed = true) registry.countIt().increment() verify { // 测试失败 registry.countIt().increment() } } @Test fun `test counter with tag`() { val registry: MeterRegistry = mockk(relaxed = true) registry.countTagged("tag").increment() verify { // 测试通过 registry.countTagged("tag").increment() } } }
第一个测试执行时会报错:
Verification failed: call 2 of 2: Counter(child of #4#6).increment()) was not called
第一个测试始终失败,第二个却能正常通过,请问这是什么原因?该如何正确验证第一个无标签指标的递增操作?
原因分析
- 无标签计数器的问题:当调用仅传名称的
counter("my-counter")时,relaxed = true创建的MockK宽松mock,每次调用都会生成全新的Counter实例。实际执行时用的是第一次调用registry.countIt()返回的实例,而verify块里再次调用registry.countIt()时,MockK又生成了第二个实例,验证自然找不到对应调用记录。 - 带标签计数器正常的原因:带标签的
counter调用会根据传入的标签参数做匹配,MockK会复用同一个Counter实例,两次调用registry.countTagged("tag")返回的是同一个对象,所以验证能命中。
解决方法
方案1:提前存根固定返回实例
手动创建Counter的mock对象,指定registry.counter("my-counter")始终返回这个固定实例,确保两次调用拿到的是同一个对象:
@Test fun `test counter`() { val registry: MeterRegistry = mockk() val counterMock: Counter = mockk() // 存根指定方法的返回值 every { registry.counter("my-counter") } returns counterMock registry.countIt().increment() // 直接验证mock实例的调用 verify { counterMock.increment() } }
方案2:捕获实例后验证
先调用方法获取Counter实例,后续直接验证这个实例的increment调用,避免二次调用生成新实例:
@Test fun `test counter`() { val registry: MeterRegistry = mockk(relaxed = true) // 先获取实例 val counter = registry.countIt() counter.increment() // 验证该实例的increment调用 verify { counter.increment() } }
内容的提问来源于stack exchange,提问作者Robert
相关产品推荐
相关产品推荐

