编写Junit测试的测试用例

时间:2010-08-03 16:19:19

标签: java eclipse unit-testing junit

作为开发人员,我是单元测试的新手,并且需要编写测试用例来对以下代码进行单元测试。有人可以帮助我,并给我一些关于如何在eclipse中编写单元测试的指针。

private void handle(final DocumentEvent e) { 
    Document doc = e.getDocument(); 
    try { 
       String text = e.getDocument().getText(0, doc.getLength()); 

       if (text.length() >= maxMessageSize) { 
            try { 
               component.getHighlighter()
                        .addHighlight(maxMessageSize, text.length() + 1, painter); 
            } catch (BadLocationException ex) { 
               System.out.println(ex.getMessage()); 
            } 
       } else { 
            component.getHighlighter().removeAllHighlights(); 
       } 
    } catch (BadLocationException e1) { 
       System.out.println(e1.getMessage()); 
    } 
} 

由于


更新

由于某种原因,当我运行测试用例时,我根本没有得到任何报道。我在这里做错了什么?进一步的研究表明我需要使用test.perform()方法来调用我想要测试的方法。这是正确的吗?你能建议吗?这是代码:

public class TestMaxLength {
  static final int maxMessageSize = 125;
  JTextPane textPane = new JTextPane();
  //***EasyMock varibles****
  private JTextComponent mockComponent;
  private MaxLength classUnderTest;
  private DocumentEvent mockEvent;
  private Document mockDocument;
  private Highlighter mockHighlighter;

  @Before public void setUp() {
    mockComponent = EasyMock.createMock(JTextComponent.class);
    mockEvent = EasyMock.createMock(DocumentEvent.class); 
    mockDocument = EasyMock.createMock(Document.class); 
    EasyMock.expect(mockEvent.getDocument()).andStubReturn(mockDocument);
    EasyMock.expect(mockDocument.getLength()).andReturn(256); 
    mockHighlighter = EasyMock.createMock(Highlighter.class); 
    EasyMock.expect(mockComponent.getHighlighter()).andReturn(mockHighlighter);
  }

  @Test public void testSetLength() { 
    MaxLength maxListener = new MaxLength(125); 
    maxListener.decorate(textPane);
  }

  @Test 
  public void testEmptyText() { 
    EasyMock.expect(mockDocument.getText(0, 1)).andStubReturn(""); 
    mockHighlighter.removeAllHighlights(); 
    EasyMock.replay(mockComponent, mockEvent, mockDocument, mockHighlighter);      
    classUnderTest.handle(mockEvent);      
    EasyMock.verify(mockComponent, mockEvent, mockDocument, mockHighlighter); 
  }     
}

decorate(JtextComponent jComponent)方法存在于要测试的类中(MaxLength),定义为:

public final void decorate(final JTextComponent c) {
  //TODO throw exception if already decorating
  this.component = c;
  component.getDocument().addDocumentListener(this);
}

更新:

@Peter:管理发现它不是Component类的问题,而是我需要asm(http://forge.ow2.org/projects/asm)。我还改变了代码,将2种方法合并为1种方法:

public void testEmptyText() 
{ 
maxSizeListener.decorate(mockComponent);
//mockHighlighter.removeAllHighlights(); 
EasyMock.replay(mockComponent, mockEvent, mockDocument, mockHighlighter); 
maxSizeListener.handle(mockEvent); 
EasyMock.verify(mockComponent, mockEvent, mockDocument, mockHighlighter); 
} 

但现在我在验证时出现了不同的错误:

java.lang.AssertionError: 
Expectation failure on verify:
getHighlighter(): expected: 1, actual: 0
at org.easymock.internal.MocksControl.verify(MocksControl.java:184)
at org.easymock.EasyMock.verify(EasyMock.java:2038)
at net.TestMaxLength.testEmptyText(TestMaxLength.java:98)

这是在mockComponent上执行EasyMock.verify()语句时引起的。

2 个答案:

答案 0 :(得分:10)

我建议使用模拟框架,例如EasyMock。模拟允许您使用所需的测试行为配置依赖项。在你的情况下,你需要一个模拟DocumentEvent,理想情况下需要另一个component,我猜这是一个类成员。

单元测试的两个方面

  • 如何进行测试,i .; e。将测试正确运行所需的正确状态的正确对象组装的技术细节(又名_test夹具),和
  • 要测试的内容,即要验证的方案。

如何测试

Eclipse支持JUnit开箱即用,因此您可以快速生成新的JUnit测试用例(在Project Explorer上下文菜单中:New - >(Other - >)JUnit - > JUnit Test Case),然后单击运行它在“运行”按钮上。

使用EasyMock(假设您可以将组件作为构造函数参数传递给测试类),在您的情况下设置测试夹具看起来像这样:

private Component mockComponent;
private ClassUnderTest classUnderTest;
private DocumentEvent mockEvent;
private Document mockDocument;
private Highlighter mockHighlighter;

@Before
public void setUp() {
    mockComponent = createMock(Component.class);
    classUnderTest = new ClassUnderTest(mockComponent);
    mockEvent = createMock(DocumentEvent.class);
    mockDocument = createMock(Document.class);
    expect(mockEvent.getDocument()).andStubReturn(mockDocument);
    expect(mockDocument.getLength()).andReturn(1);
    mockHighlighter = createMock(Highlighter.class);
    expect(mockComponent.getHighlighter()).andReturn(mockHighlighter);
}

@Test
public void testEmptyText() {
    expect(mockDocument.getText(0, 1)).andStubReturn("");
    mockHighlighter.removeAllHighlights();
    replay(mockComponent, mockEvent, mockDocument, mockHighlighter);

    classUnderTest.handle(mockEvent);

    verify(mockComponent, mockEvent, mockDocument, mockHighlighter);
}

此测试假设默认情况下maxMessageSize至少为1 - 测试的maxMessageSize设置为练习,因为您发布的代码段不能提供任何线索。

测试什么

您显示的方法从与事件关联的文档中获取文本,然后根据其长度,它执行不同的操作。我至少会写下以下单元测试:

  • 使用maxMessageSize == 0
  • 的空文档文字
  • 使用maxMessageSize > 0
  • 的空文档文字
  • 带有maxMessageSize == text.length()
  • 的非空文档文字
  • 带有maxMessageSize > text.length()
  • 的非空文档文字
  • maxMessageSize < text.length()addHighlight()投掷BadLocationException
  • 的非文档文字

注释

  1. 感知BadLocationException有点棘手,因为它产生的只是stdout的输出;幸运的是,您可以通过System.setOut轻松重新分配标准输出。但是,您可能需要考虑改进异常处理,至少使用日志框架而不是打印到stdout。
  2. 来自代码的
  3. 似乎其他方法(例如removeAllHighlights()和/或getText())也可能抛出BadLocationException,但try-catch块的组织不当。我会考虑在这些方法抛出时添加更多单元测试,然后重构异常处理代码。
  4. 更新

      

    我以为我做的事情有问题...请你提供修改/更正的代码吗???

    您的testSetLength方法并未真正测试任何内容 - 您需要断言语句(和/或EasyMock验证),以便您的单元测试能够实际验证某些行为。但是,它提供了设置测试类的缺失线索。所以我尝试统一你的两个测试方法来创建一个有希望工作的方法(我是从内存写的,所以我不能保证它会在第一次尝试时完全编译和运行):

      @Test 
      public void testEmptyText() { 
        // set up the test class with a specific max length
        classUnderTest = new MaxLength(125); 
        // this shall be called from inside decorate()
        mockDocument.addDocumentListener(classUnderTest); 
        // the mock document shall always return an empty text
        EasyMock.expect(mockDocument.getText(0, 1)).andStubReturn(""); 
        // we expect this to be called from inside handle()
        mockHighlighter.removeAllHighlights();
        // start replay mode
        EasyMock.replay(mockComponent, mockEvent, mockDocument, mockHighlighter); 
        // inject mock component into tested object
        maxListener.decorate(mockComponent); 
    
        // call the tested method
        classUnderTest.handle(mockEvent); 
    
        // verify that all expected calls to the mocks have been made    
        EasyMock.verify(mockComponent, mockEvent, mockDocument, mockHighlighter); 
      }
    

答案 1 :(得分:4)

当您编写单元测试时,您尝试测试(在这种情况下)该方法是否执行了它应该执行的操作。您应该查看实现并从中编写测试。相反,你应该考虑方法应该能够处理什么输入,以及调用方法后结果(返回值和/或副作用)应该是什么。

然后你应该编写一个或多个用有效和无效输入调用方法的测试,并使测试确认结果与你认为会发生的结果相符。

这是一个简短且不完整的描述,请在Wikipediajunit.org详细了解。

以下是JUnit in Eclipse的旧版(2005年)工作指南。