標準 JUnit 依賴 Reflection(反射) 自動發現並執行測試方法,但 CLDC/MIDP 環境不提供 Reflection API。J2MEUnit (17KB) 由 Kent Beck & Erich Gamma 移植,引入「手動 Suite 組裝 + TestMethod 回調」機制,填補了單元測試空白。
Properties → Java Build Path → Libraries → Add External JARs 選中 J2MEUnit.jar
public class TestOne extends TestCase {
// 必須提供帶參構造器(框架反射替代品)
public TestOne(String sTestName, TestMethod rTestMethod) {
super(sTestName, rTestMethod);
}
// 可選:setUp/tearDown
protected void setUp() { /* 初始化資源 */ }
protected void tearDown() { /* 釋放資源 */ }
// 測試方法命名慣例以 test 開頭
public void testOne() {
System.out.println("TestOne.testOne()");
assertTrue("Should be true", false); // 故意失敗示範
}
public void testTwo() {
System.out.println("TestOne.testTwo()");
throw new RuntimeException("Exception");
}
// 關鍵:手動組裝 Suite
public Test suite() {
TestSuite aSuite = new TestSuite();
// 匿名內部類綁定單一測試方法
aSuite.addTest(new TestOne("testOne", new TestMethod() {
public void run(TestCase tc) { ((TestOne)tc).testOne(); }
}));
aSuite.addTest(new TestOne("testTwo", new TestMethod() {
public void run(TestCase tc) { ((TestOne)tc).testTwo(); }
}));
return aSuite;
}
}
若在單一 run() 中連續調用多個測試,前者失敗會導致後者不執行,且無法精準定位錯誤。老老實實寫 suite(),一個測試一個 TestCase 實例。
public class TestAll extends TestCase {
public Test suite() {
TestSuite suite = new TestSuite();
suite.addTest(new TestOne().suite());
suite.addTest(new TestTwo().suite());
return suite;
}
}
| 模式 | 適用場景 | 啟動方式 |
|---|---|---|
| TextUI | 桌面開發機、CI 自動化 | TestRunner.main(new String[]{"pkg.TestAll"}) |
| MIDletUI | 真機/模擬器實測 | 繼承 J2MEUnit.midletui.TestRunner,start(new String[]{"pkg.TestAll"}) |
MIDletUI 更迷人:真機上跑單測,極大降低測試成本。也可在 JAD 增加 J2MEUnitTestClasses 屬性列出測試類,無需修改主類。
testXxx(),邊界條件、異常路徑全覆蓋setUp() 初始化 Mock 物件,tearDown() 釋放 RMS/網絡資源assertEquals(expected, actual, msg) 而非單純 assertTrue,失敗訊息更可讀J2MEUnit 雖缺反射帶來的便利,但以 17KB 體積換來可在真機跑自動化單測的能力,對嵌入式開發極具價值。將單測納入日常流程,能在早期攔截 70% 以上邏輯 Bug,是 J2ME 專案質量的基石。