为Junit测试编写测试用例

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

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:Managed发现它不是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); } 

但是现在我在validation时遇到了不同的错误:

 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()语句时引起的。

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

unit testing的两个方面

  • 如何测试,我…; e。 将测试正确运行所需的正确状态的正确对象组装的技术细节(也就是_test夹具),以及
  • 要测试什么 ,即要validation的场景。

怎么测试

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

在您的情况下设置测试夹具看起来像这样,使用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设置为练习,因为您发布的代码片段没有提供任何线索。

测试什么

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

  • maxMessageSize == 0空文档文本
  • maxMessageSize > 0空文档文本
  • maxMessageSize == text.length()非空文档文本maxMessageSize == text.length()
  • maxMessageSize > text.length()非空文档文本
  • 带有maxMessageSize < text.length()非空文档文本maxMessageSize < text.length()addHighlight()抛出BadLocationException

笔记

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

更新

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

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

  @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); } 

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

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

这是一个简短且不完整的描述,请阅读Wikipedia和junit.org 。

这是一本旧的(2005)但是在Eclipse中使用JUnit的工作指南。