如何進行千分尺單元測試
1.概述
在本文中,我們將探討如何在 Spring Boot 應用程式中對 Micrometer 指標進行單元測試。我們將重點介紹如何使用簡單的儀表註冊表以程式設計方式測試儀表。
單元測試指標對於確保我們的應用程式正確追蹤效能數據和業務指標至關重要。透過使用 Micrometer 的SimpleMeterRegistry
,我們可以建立獨立的測試來驗證我們的指標收集,而無需完整的 Spring 上下文。
當涉及整合測試時,我們將學習如何重置MeterRegistry
以在@SpringBootTest
期間對其執行斷言。
2. 測試千分尺
讓我們從一個使用 Micrometer 記錄指標的簡單服務開始。我們的FooService
使用MeterRegistry
來透過計數器追蹤方法counter
,並透過timer
追蹤執行時間:
@Service
class FooService {
// constructor
private final MeterRegistry registry;
public int foo() {
int delayedMs = registry.timer("foo.time")
.record(this::doSomething);
registry.counter("foo.count")
.increment();
return delayedMs;
}
private int doSomething() { /* ... */ }
}
2.1. 單元測試
對於單元測試,我們可以透過程式設計方式建立一個SimpleMeterRegistry
並將其註入到我們的服務中。這種方法允許我們單獨測試指標收集,而無需 Spring Boot 的自動配置:
class MicrometerUnitTest {
MeterRegistry meterRegistry = new SimpleMeterRegistry();
FooService fooService = new FooService(meterRegistry);
@Test
void whenFooIsCalled_thenCounterIsIncremented() {
fooService.foo();
fooService.foo();
fooService.foo();
double invocations = meterRegistry.get("foo.count")
.counter()
.count();
assertThat(invocations)
.isEqualTo(3);
}
}
如我們所見,我們使用meterRegistry.get()
方法按名稱檢索儀表,然後存取其記錄的值。對於計數器,我們呼叫count()
來取得增量的總次數。同樣,對於timers
或其他類型的儀表,我們可以使用meterRegistry
尋找儀表實例並執行相關的斷言。
SimpleMeterRegistry
將所有指標儲存在記憶體中,使其非常適合單元測試,我們希望驗證我們的應用程式是否正確記錄指標,而無需完整監控系統設定的開銷。
2.2. 整合測試
如果我們想在@SpringBootTest
期間測試這些儀表,我們可能會注意到不同的行為,特別是當多個測試呼叫我們測試的元件時:
@SpringBootTest(classes=FooApplication.class)
class MicrometerIntegrationTest {
@Autowired
private MeterRegistry meterRegistry;
@Autowired
private FooService fooService;
@Test
void whenFooIsCalled_thenCounterIsIncremented() {
fooService.foo();
fooService.foo();
fooService.foo();
double invocations = meterRegistry.get("foo.count")
.counter()
.count();
assertThat(invocations)
.isEqualTo(3); // <-- this can fail, depending on the order of the test execution
}
@Test
void whenFooIsCalled_thenTimerIsUpdated() {
// ...
}
}
在這種情況下,儀表註冊表在所有測試方法之間共用。因此, meters
會累積先前測試執行的值,這可能會導致我們的斷言失敗。
為了解決這個問題,我們可以在每次測試之前或之後清除meterRegistry
:
@SpringBootTest(classes = FooApplication.class )
class MicrometerIntegrationTest {
@Autowired
private MeterRegistry meterRegistry;
@Autowired
private FooService fooService;
@BeforeEach
void reset() {
meterRegistry.clear();
}
@Test
void whenFooIsCalled_thenCounterIsIncremented() {
// ...
}
@Test
void whenFooIsCalled_thenTimerIsUpdated() {
// ...
}
}
3. 千分尺測試模組
對於簡單的斷言,我們甚至可以匯入專用的[micrometer-test](https://mvnrepository.com/artifact/io.micrometer/micrometer-test)
模組:
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-test</artifactId>
<version>1.15.3</version>
<scope>test</scope>
</dependency>
這將允許我們使用一組類似 AssertJ 的斷言來驗證特定儀表是否已註冊:
@Test
void whenFooIsCalled_thenTimerIsRegistered() {
fooService.foo();
MeterRegistryAssert.assertThat(meterRegistry)
.hasTimerWithName("foo.time");
}
如我們所見, Micrometer 的測試專用模組使我們能夠編寫優雅的斷言,儘管它僅用於檢查指標的存在性。對於其餘部分,例如檢查儀表記錄的確切值,我們需要編寫自己的斷言。
4. 結論
在本簡短教學中,我們示範如何使用SimpleMeterRegistry
對 Micrometer 指標進行單元測試。我們討論如何使用meterRegistry
以程式設計方式取得儀表並對收集的值執行斷言來測試各種儀表。
之後,我們學習瞭如何在整合測試中對儀表執行斷言。如我們所見,測試方法非常相似,唯一顯著的差異是,使用SpringBootTest
時,我們需要在每次測試前清除MeterRegistry
。
與往常一樣,本文中提供的程式碼可在 GitHub 上取得。