Junit实现接口类测试
寫接口的目的一般是,讓這個接口的所有實現都具備某個共同的行為。這個行為不僅目前實現的類具備,將來要寫的實現也都必須具備。因此,就需要為這個接口編寫一個通用的測試程序,這個測試程序不僅能測試當前已經實現的類的通用屬性,而且可以不加修改應用于將來要實現的類。
首先引入一個抽象的測試類,該測試類的方法用于測試接口的共同行為。然后使用工廠方法創建接口的對象,以完成測試程序。下面是詳細步驟:
1.???? 選定測試程序要測試的已經具體實現的類。
2.???? 創建一個抽象的測試類,聲明要驗證的功能的測試方法。在具體的測試程序實現中繼承這個測試類,并修改相應的實現方法。
3.???? 在接口的每一個具體實現中都運行該測試程序,但在每個實現中都只驗證“接口范圍內”的行為[10]。
4.???? 在測試程序內,找到創建(接口)對象的代碼,將該代碼改成具體的、已經實現的類的創建方法,但記住將該對象聲明為接口的對象,而不是具體實現的類的對象。重復這一過程,直至測試程序中沒有已經實現的類的對象。
5.???? 聲明你要在測試中調用的抽象方法。
6.???? 現在,測試只涉及接口和一些抽象的測試方法,請將測試程序移入抽象的測試類。
7.???? 重復這一過程直至所有的測試都移入抽象的測試類。
8.???? 重復前面的全部過程,直至除了驗證具體實現的特有的方法的測試程序外,所有的測試代碼都已完成。
下面通過測試java.util.Iterator接口來具體說明這種技巧。首先讓我們看代碼ListIteratorTest,這是測試java.util.Listiterator接口的一個具體實現。
package junit.cookbook.test;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import static org.junit.Assert.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
?
public class ListIteratorTest {
?????? private Iterator noMoreElementsIterator;
?????? protected abstract Iterator makeNoMoreElementsIterator();
?
?????? @Before
?????? public void setUp() throws Exception {
????????????? List empty = new ArrayList();
????????????? noMoreElementsIterator = empty.iterator();
?????? }
?????? @Test
?????? public void testHasNextNoMoreElements() {
????????????? assertFalse(noMoreElementsIterator.hasNext());
?????? }
?????? @Test
?????? public void testNextNoMoreElements() {
????????????? try {
???????????????????? noMoreElementsIterator.next();
???????????????????? fail("No exception with no elements remaining!");
????????????? } catch (NoSuchElementException expected) {
????????????? }
?????? }
?????? @Test
?????? public void testRemoveNoMoreElements() {
????????????? try {
???????????????????? noMoreElementsIterator.remove();
???????????????????? fail("No exception with no elements remaining!");
????????????? } catch (IllegalStateException expected) {
????????????? }
?????? }
}
接著讓引入抽象的IteratorTest測試類,并將ListIteratorTest類的實際的實現添加到IteratorTest。結果如下所示:
package junit.cookbook.test;
import java.util.Iterator;
import java.util.NoSuchElementException;
import static org.junit.Assert.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
?
public abstract class IteratorTest {
?????? private Iterator noMoreElementsIterator;
?????? protected abstract Iterator makeNoMoreElementsIterator();
?????? @Before
?????? public void setUp() throws Exception {
????????????? noMoreElementsIterator = makeNoMoreElementsIterator();
?????? }
?????? @Test
?????? public void testHasNextNoMoreElements() {
????????????? assertFalse(noMoreElementsIterator.hasNext());
?????? }
?????? @Test
?????? public void testNextNoMoreElements() {
????????????? try {
???????????????????? noMoreElementsIterator.next();
???????????????????? fail("No exception with no elements remaining!");
????????????? } catch (NoSuchElementException expected) {
????????????? }
?????? }
?????? @Test
?????? public void testRemoveNoMoreElements() {
????????????? try {
???????????????????? noMoreElementsIterator.remove();
???????????????????? fail("No exception with no elements remaining!");
????????????? } catch (IllegalStateException expected) {
????????????? }
?????? }
}
?
只要我們實現了makeNoMoreElementsIterator()方法,我們就可以將所有的測試移入IteratorTest類。我們只需要將這個方法封裝到ListIteratorTest類中:
package junit.cookbook.test;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.junit.After;
import org.junit.Before;
import temp.IteratorTest;
?
public class ListIteratorTest extends IteratorTest {
?????? protected Iterator makeNoMoreElementsIterator() {
????????????? List empty = new ArrayList();
????????????? return empty.iterator();
?????? }
}
?ListIteratorTest繼承我們的抽象類IteratorTest。
我們的ListIteratorTest類中實現的創建方法返回一個iterator而不是一個空列表。類似地,如果以測試一個基于Set類的iterator,你應該創建一個繼承IteratorTest的SetIteratorTest類,這個類的makeNoMorelementsterator()方法也應該返回相應的iterator而不是一個空的Set對象。
這個抽象的test case能正常工作的原因是Junit中的測試等級規定。一個TestCase類在繼承其父類時將同時繼承父類所有的測試。在例子中,ListIteratorTest繼承IteratorTest,所以只要在test runner中運行ListIteratorTest,IteratorTest中的測試都將得到運行。
值得一提的是Eric Armstrong的觀點,他是Yahoo!的JUnit社區常客:“一個接口只定義語法,而不指定語義,雖然他們經常被實現。另一方面,一個相關的test Suite可以指定語義。我們應該給每一個公用的接口配備一個test suite!”當我們在框架中發布一個接口或者抽象類的時候,最好同時寫一個相關的抽象的Test Case,以驗證框架在所有客戶端中的最重要的期望值。
最后,你會有同時實現了多個接口的類。建議你獨立地測試每個接口的功能,而不要拘泥于那個“一個test case類測試一個類”的死板規定。
轉載于:https://www.cnblogs.com/Automation_software/archive/2011/01/24/1943054.html
總結
以上是生活随笔為你收集整理的Junit实现接口类测试的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Oracle 不同用户之间 大量数据转移
- 下一篇: 【译文】Web Farm和Web Gar