2013-09-26 25 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的情况下对其进行测试的一种方式。