使用單元測試可以隔離開其他與本次開發不相干的諸多因素,普通的jave項目可以在測試類中直接註解@Test標註單元測試方法,當測試項目中測試的方法中有涉及使用spring進行管理bean時,spring提供了一種比較便捷的解決方案。以下以現進行開發的項目環境做說明,將對環境、配置及常見問題進行說明。
項目環境:
開發工具myeclipse,項目管理工具maven,項目爲spring batch實現的批處理程序【使用sping進行管理相關bean】
關鍵配置:
- 在pom.xml文件中增加繼承測試使用的依賴【詳見代碼1】
- 配置單元測試類【詳見代碼2】
- 運行
1. 可以使用maven進行運行如下圖,最好在pom的開發環境中添加插件maven-surefire-plugin【詳見代碼3】,可以生成報告,不配置的話測試打印日誌可能亂碼。
2. 也可以通過run as->junit test方式運行
代碼1
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>3.2.0.RELEASE</version>
<scope>test</scope>
</dependency>
代碼2-1
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:spring/applicationContext.xml",
"classpath:spring/common-datasource.xml",
"classpath:spring/common-batch.xml",
"classpath:spring/dataAccessContext-local-dev.xml" })
public abstract class SpringJunitBaseTest {
@Autowired
protected JobLauncher jobLauncher;
@Autowired
@Qualifier("traditPolicyOfBisToNbzJob")
protected Job job;
protected Long startTime;
@Before
public void beforeMethod() {
System.out.println("測試執行前>>>>>>>>");
startTime = System.currentTimeMillis();
}
@After
public void afterMethod() {
System.out.println("測試執行後<<<<<<<<");
Long takeTime = System.currentTimeMillis() - startTime;
StringBuffer takeTimeShow = new StringBuffer("執行結束,總耗時【");
Long minutes = takeTime / 60000;
Long seconds = takeTime % 60000 / 1000;
Long mills = takeTime % 1000;
takeTimeShow.append(minutes + "分" + seconds + "秒" + mills + "毫秒");
takeTimeShow.append("】");
System.out.println(takeTimeShow);
}
@Test
public void test() {
try {
jobLauncher.run(job, getJobParameter());
} catch (JobExecutionAlreadyRunningException e) {
e.printStackTrace();
} catch (JobRestartException e) {
e.printStackTrace();
} catch (JobInstanceAlreadyCompleteException e) {
e.printStackTrace();
} catch (JobParametersInvalidException e) {
e.printStackTrace();
}
}
public abstract JobParameters getJobParameter();
}
代碼2-2
@ContextConfiguration(locations = {
"classpath:spring/jobConfig/batchForTraditPolicyOfBisToNbz.xml",
"classpath:spring/jobConfig/batchForTraditPolicyOfBisToNbzBean-dev.xml",
"classpath:spring/dataAccessContext-local2-dev.xml",
"classpath:spring/dataAccessContext-prps-dev.xml" })
public class TraditPolicyOfBisToNbzJobTest extends SpringJunitBaseTest {
@Autowired
@Qualifier("traditPolicyOfBisToNbzJob")
protected Job job;
@Override
public JobParameters getJobParameter() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
Date now = new Date();
return new JobParametersBuilder().addString("batchId",
"TRADIT_POLICY_TO_BIS_" + sdf.format(now)).toJobParameters();
}
}
代碼3-maven-surefire-plugin插件
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<extensions>true</extensions>
<version>2.19</version>
<configuration>
<testFailureIgnore>false</testFailureIgnore>
<argLine>${maven.test.jvmargs}</argLine>
<testFailureIgnore>true</testFailureIgnore>
<excludes>
<exclude>**/SpringJunitBaseTest.java</exclude>
</excludes>
</configuration>
</plugin>
代碼2說明
在項目做單元測試時,尤其項目較大時,由於每個單元測試之間的差異都不是很大,有很多共同內容,一般做一個抽象在後續的單元測試編寫會省時不少,代碼也更優雅,以上代碼2-1位抽象單元測試類,在上下文配置【ContextConfiguration】上,父子類也存在繼承關係【PS:inheritLocations屬性:如果設置爲false,將屏蔽掉父類中使用該註解指定的配置文件位置,默認爲true表示繼承父類中使用該註解指定的配置文件位置】。
異常說明 :
java.lang.NoClassDefFoundError: Could not initialize class org.springframework.test.context.junit4.SpringJUnit4ClassRunner
如果你運氣不好,很可能碰到這個異常,單元測試失敗,什麼原因?junit跟spring test有版本兼容問題,特別需要注意。以上配置中的junit跟spring test是兼容的。