Spring Boot測試時使用@ActiveProfiles
決定測試類是否啟用@EnableScheduling
的方式如下。
一般執行時可使用@ConditionalOnProperty
來決定是否套用@EnableScheduling
來啟用排程。而在Spring Boot測試時再利用@ActiveProfiles
決定測試類執行時是否啟用@EnableScheduling
。
@ActiveProfiles
的value
值代表測試時使用的properites,所以可以透過設定不同的properties來作為不同測試時使用的properties。
在application.properties
設定spring.profiles.active
決定一般執行時使用的properties。例如設定執行時使用application-test.properties
。
application.properties
spring.profiles.active=test
application-test.properties
的scheduling.enabled
為false
。
application-test.properties
#Scheduling
scheduling.enabled=false
application-test.properties
的scheduling.enabled
為true
。
application-prod.properties
#Scheduling
scheduling.enabled=true
在配置類SchedulingConfig
的@EnableScheduling
前加上@ConditionalOnProperty
設定如下。
SchedulingConfig
package com.abc.demo.config;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
@ConditionalOnProperty(
value = "scheduling.enabled", // 讀取application-xxx.properties的scheduling.enabled的值
havingValue = "true", // scheduling.enabled為true則套用下面的annotation即@EnableScheduling的效果,反之@EnableScheduling會無效果
matchIfMissing = false // default, 若scheduling.enabled沒設定則預設為false
)
@EnableScheduling // 依上面@ConditionalOnProperty的條件決定是否套用
@Configuration
public class SchedulingConfig {
}
DemoScheduleTask
及DemoService
為被測試的對象。
DemoScheduleTask
為排程程式;
DemoService
為一般(非排程)程式。
DemoScheduleTask
package com.abc.demo.schedule;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class DemoScheduleTask {
@Scheduled(fixedRate = 3000)
public void printUnixEpochTime() {
System.out.println(System.currentTimeMillis());
}
}
DemoService
package com.abc.demo.service;
import org.springframework.stereotype.Service;
@Service
public class DemoService {
public int plus(int x, int y) {
return x + y;
}
}
DemoScheduleTaskTests
為測試DemoScheduleTask
排程的測試類,執行時要啟用@EnableScheduling
,@ActiveProfiles
的值設為prod
,代表測試執行時使用application-prod.properties
的設定,也就是scheduling.enabled=true
。
DemoScheduleTaskTests
package com.abc.demo.schedule;
import org.awaitility.Awaitility;
import org.awaitility.Durations;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.test.context.ActiveProfiles;
@ActiveProfiles("prod")
@SpringBootTest
class DemoScheduleTaskTests {
private final static int MIN_NUMBER_OF_INVOCATIONS = 2;
@SpyBean // 用@SpyBean才可被Mockito.verify驗證備測試對象的調用次數
private DemoScheduleTask demoScheduleTask;
/**
* 測試DemoScheduleTask.printUnixEpochTime()在10秒鐘至少被執行2次
*/
@Test
void printUnixEpochTime_testInvocationAtLeastTwoTimesDuringTenSeconds() {
Awaitility.await()
.atMost(Durations.TEN_SECONDS) // 等待期間10秒
.untilAsserted( // 直到assert發生停止等待
() -> Mockito.verify(demoScheduleTask, Mockito.atLeast(MIN_NUMBER_OF_INVOCATIONS))
.printUnixEpochTime()); // 驗證demoScheduleTask.printUnixEpochTime()被調用2次
}
}
DemoServiceTests
為測試DemoService
的測試類,執行時不啟用@EnableScheduling
,@ActiveProfiles
的值設為test
,代表測試執行時使用application-test.properties
的設定,也就是scheduling.enabled=false
。
DemoServiceTests
package com.abc.demo.service;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
@ActiveProfiles("test")
@SpringBootTest
class DemoServiceTests {
@Autowired
private DemoService demoService;
@Test
void plus_test() {
int x = 1;
int y = 2;
int actual = demoService.plus(x, y);
int expected = x + y;
Assertions.assertEquals(expected, actual);
}
}
則執行DemoScheduleTaskTests
中的測試方法時會啟用排程;
執行DemoServiceTests
中的測試方法時不會啟用排程。
參考github。
沒有留言:
張貼留言