springboot junit測試

泛舟瓦尔登湖發表於2024-06-11

這邊記錄的不是怎麼在springboot下作測試,而是最近在學習測試時遇到的一個有趣的問題。
囉嗦兩句,一直覺得單元測試很重要,但我在以前的工作中發現很少有人重視,或者很少有人去寫這個單元測試,其實單元測試也不難,關鍵得上手,慢慢就會有感覺,但說實話一開始不會寫的話,需要有個樣例,這樣你去琢磨它,學著寫2個應該很快就能上手。另外一點是從測試開始讀別人專案的程式碼也不失為一個好辦法,我最近在讀別人程式碼時,想搞清楚它的多資料來源是怎麼做的,於是我就對Dao層做簡單的測試呼叫。如下面第一個方法,看起來很簡單,@TestExecutionListeners和RequestHeaderSettingTestExecutionListener 這個類請忽略,它正是為了解決我遇到的問題的。我遇到的問題是這樣的,我只是簡單的執行dao方法,但是底層在實際獲取資料庫連線時會選擇一個資料來源,上面也說了專案用了動態資料來源,那麼它在獲取動態資料來源時的一個演算法是根據請求頭裡的標記(即我下面的示例header:yourHeader)的值決定去取哪個資料來源的連線,讓我納悶的是我這執行的是dao方法,但是程式在執行(ServletRequestAttributes)RequestContextHolder.getRequestAttributes().getRequest()時,居然可以拿到這個請求,這是什麼情況,這個我理解是啟用的springboottest,建立了請求上下文。我現在要做的就是在請求頭中傳入我想呼叫的資料來源key。因此使用@TestExecutionListeners和自定義類RequestHeaderSettingTestExecutionListener可以實現這一點。

@Slf4j
@SpringBootTest
@RunWith(SpringRunner.class)//新增這行下面的xxDao才會注入
@TestExecutionListeners(
        listeners = RequestHeaderSettingTestExecutionListener.class, //這是自定義的
        mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS)//會自動合併自定義的監聽器和預設的監聽器。防止衝突導致xxDao無法注入
public class xxDaoTest {
    @Autowired
    XxDao xxDao;

    @Test
    public void testGetActionByName() {
        Assert.assertNotNull("無記錄", idsDao.getActionByName("test"));
    }
}

public class RequestHeaderSettingTestExecutionListener extends AbstractTestExecutionListener {

    @Override
    public void beforeTestMethod(TestContext testContext) throws Exception {
        // 在測試方法執行前設定模擬的請求頭
        MockHttpServletRequest request =  new MockHttpServletRequest();
        request.addHeader("yourHeader","itsValue");//這邊設定後續要透過(ServletRequestAttributes)RequestContextHolder.getRequestAttributes().getRequest()獲取的header
        ServletRequestAttributes attributes = new ServletRequestAttributes(request);
        RequestContextHolder.setRequestAttributes(attributes);
    }

    @Override
    public void afterTestMethod(TestContext testContext) throws Exception {
        // 清理請求上下文,避免影響其他測試
        RequestContextHolder.resetRequestAttributes();
    }
}

相關文章