2013-09-26 26 views
2

對於我的類,我們創建ArrayStacks和LinkedStacks,而不是使用J-Unit進行測試。我們的一個測試是使用clear()方法。我們的教授特別要求我們清空堆棧中的每個元素,並測試它們是否爲空。我該怎麼做呢?J-Unit測試數組堆棧中的clear()方法

public void clear() { 
    // Checks if this stack is empty, 
    // otherwise clears this stack. 

    if(!isEmpty()){ 
     for(int i = 0; i < sizeIs(); i++){ 
      pop(); 
     } 
     topIndex = -1; 
    } 
} 


public class Test_clear { 

/* 
* Class to test the clear method added to the Stack ADT of Lab04 
* 
* tests clear on an empty stack 
*  a stack with one element 
*  a stack with many (but less than full) elements 
*  and a "full" ArrayStack (not applicable to Linked Stack - comment it out) 
*/ 

    ArrayStack stk1, stk2; 

@Before 

public void setUp() throws Exception { 
    stk1 = new ArrayStack(); stk2 = new ArrayStack(); 
} 

@Test 
public void test_clear_on_an_emptyStack() { 

    stk1.clear(); 

    Assert.assertEquals(true, stk1.isEmpty()); 
} 

@Test 
public void test_clear_on_a_stack_with_1_element() { 

    stk1.push(5); 

    stk1.clear(); 

    Assert.assertEquals(true, stk1.isEmpty())' 
} 

等等。但是檢查isEmpty()上的assertEquals將不會測試數組中的元素是否被清除。提前致謝!

+0

該數組是'private',或者應該是。所以也請參閱http://stackoverflow.com/questions/34571/whats-the-proper-way-to-test-a-class-with-private-methods-using-junit – Raedwald

回答

3

爲了測試數組是否正確地清除了從堆棧彈出的元素的引用,您必須有一些方法可以在測試期間直接訪問數組。

也許有一個包私有方法返回(防禦副本)的支持數組?

2

從學習Java的來龍去脈這種練習是值得的,我會建議您慎重,然後再將其應用於其他問題

鼓勵使用JUnit來鍛鍊你的課堂的公共接口。在ArrayStack的情況下,我們假設它有幾個方法:

  • void push(Object o)
  • Object pop()
  • void clear()

@dkaztzel提出一個解決方案 - 實施一攬子私人方法來防禦性複製內部堆棧的內容。比方說,它看起來像這樣:

Object[] getStack() { 
    return stack.clone(); 
} 

假設你已經實現了幾個單元測試,以驗證pushpop正在按預期(包括空和滿堆邊緣的情況下),那麼你會創建一個單元測試如下:

@Test 
public void probablyNotAGoodTest() { 
    ArrayStack arrayStack = new ArrayStack(); 
    arrayStack.push("Luke"); 

    arrayStack.clear(); 

    Object[] stackCopy = arrayStack.getStack(); 
    assertNull(stackCopy[0]); 
} 

這實現你的驗證,其實你已經設置的值指數爲null一旦元素被彈出的意圖。我總是有點可疑當我必須寫產品代碼,其唯一目的是幫助我測試我的合同。並不是說這種做法是錯誤的,但它需要仔細考慮。這裏的要求是確保彈出的對象實際上從內部堆棧中移除,所以也許這是可以的。

另一種方法是豐富ArrayStack接口,並提供一種方法來檢索給定索引處的特定對象。如果遇到空對象,此方法可能會引發異常,然後您可以對此進行測試。這裏的方法和測試可能是什麼樣子(你使用此之前,請做一些額外的驗證):

public Object getObjectAtIndex(int i) { 
    if (i >= maxSize) { 
     throw new IllegalArgumentException(); 
    } 
    if (stack[i] == null) { 
     throw new NullPointerException(); 
    } 

    return stack[i]; 
} 

然後測試:

@Test(expected=NullPointerException.class) 
public void tryToGetAClearedObject() { 
    ArrayStack arrayStack = new ArrayStack(); 
    arrayStack.push("Luke"); 
    arrayStack.clear(); 
    arrayStack.getObjectAtIndex(0); 
} 

祝你好運!

0

正如其他答案所暗示的,null輸出存儲陣列不能直接由公共API驗證。添加protected方法以允許直接檢查存儲是最簡單的。

作爲替代方案,請考慮此功能的原因:調用clear時,應釋放數組中保留的任何引用。您只能使用公共API(Reference)和一些關於GC的假設(Is there a way to FORCE weak and/or soft referenced objects to be GC'd in Java?)進行測試。

放置在堆棧上的對象,保留了Reference,然後clear它:

ReferenceQueue queue = new ReferenceQueue(); 
PhantomReference ref = addObjectToStackAndCreateReference(arrayStack, queue); 

arrayStack.clear() 

有獨立的實用方法,以保持該對象關閉Java堆棧,這可以防止集合:

private static PhantomReference addObjectToStackAndCreateReference(ArrayStack arrayStack, ReferenceQueue queue) 
{ 
    Object o = new Object(); 
    PhantomReference ref = new PhantomReference(o, queue); 
    arrayStack.push(o); 
    return ref; 
} 

現在,請驗證是否沒有剩餘對象的引用,以便引用已排入隊列中:

System.gc(); 
assertSame(ref, queue.remove()); 

我建議添加方法使測試更簡單;但是,這是您可以在不添加任何僅測試API的情況下對其進行測試的一種方式。