早期 JUnit 3 + Spring 舊版 TestContext 寫法:
public class HelloworldTest extends AbstractSingleSpringContextTests {
private Foo foo = createMock(Foo.class);
private Bar bar = createMock(Bar.class);
private Helloworld helloworld;
@Before
public void before() {
reset(foo, bar);
helloworld = new Helloworld(foo, bar);
}
@After
public void after() { verify(foo, bar); }
@Test
public void shouldSayHello() {
replay(foo, bar);
helloworld.sayHello();
}
}
缺點顯而易見:
<bean id="mockFoo" class="org.easymock.EasyMock" factory-method="createMock">
<constructor-arg index="0" value="com.example.Foo"/>
</bean>
利用 @ContextConfiguration("test-context.xml") 載入測試專屬上下文,僅定義 Mock 及被測物件:
<bean id="helloworld" class="com.example.Helloworld" autowire="byType"/>
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("test-context.xml")
public class HelloworldTest {
@Autowired private Foo foo;
@Autowired private Bar bar;
@Autowired private Helloworld helloworld;
// ... 測試方法
}
優點:零樣板代碼創建 Mock,依賴注入自動完成,測試類成純 POJO。
觀察發現:測試類中所有 @Autowired 欄位若為 Mock 物件(即動態代理或 CGLIB 增強類),則需統一驗證。編寫工具類:
public final class MockTestHelper {
public static void resetAll(Object testObject) {
reset(getDeclaredMockedFields(testObject));
}
public static void replayAll(Object testObject) {
replay(getDeclaredMockedFields(testObject));
}
public static void verifyAll(Object testObject) {
verify(getDeclaredMockedFields(testObject));
}
private static Object[] getDeclaredMockedFields(Object testObject) {
List
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("test-context.xml")
public class HelloworldTest {
@Autowired private Foo foo;
@Autowired private Bar bar;
@Autowired private Helloworld helloworld;
@Before public void before() { MockTestHelper.resetAll(this); }
@After public void after() { MockTestHelper.verifyAll(this); }
@Test
public void shouldSayHello() {
MockTestHelper.replayAll(this);
helloworld.sayHello();
// 斷言驗證
}
}
新增 Mock 欄位時,零修改驗證邏輯,Helper 自動掃描處理。
EasyMock 需 replay/verify 切換狀態,語法較繁。推薦 Mockito:
when(mock.foo()).thenReturn(bar)。replay/verify,預設驗證調用次數。Spring 2.5 的 Annotation 驅動測試框架 + 反射掃描,徹底消除 Mock 測試的樣板代碼,讓測試類回歸業務意圖表達。配合 Mockito 更能提升可讀性與維護性。