作为开发人员,我是单元测试的新手,并且需要编写测试用例来对以下代码进行单元测试。有人可以帮助我,并给我一些关于如何在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()语句时引起的。
答案 0 :(得分:10)
我建议使用模拟框架,例如EasyMock。模拟允许您使用所需的测试行为配置依赖项。在你的情况下,你需要一个模拟DocumentEvent
,理想情况下需要另一个component
,我猜这是一个类成员。
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
BadLocationException
有点棘手,因为它产生的只是stdout的输出;幸运的是,您可以通过System.setOut轻松重新分配标准输出。但是,您可能需要考虑改进异常处理,至少使用日志框架而不是打印到stdout。removeAllHighlights()
和/或getText()
)也可能抛出BadLocationException
,但try-catch
块的组织不当。我会考虑在这些方法抛出时添加更多单元测试,然后重构异常处理代码。我以为我做的事情有问题...请你提供修改/更正的代码吗???
您的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)
当您编写单元测试时,您尝试测试(在这种情况下)该方法是否执行了它应该执行的操作。您应该不查看实现并从中编写测试。相反,你应该考虑方法应该能够处理什么输入,以及调用方法后结果(返回值和/或副作用)应该是什么。
然后你应该编写一个或多个用有效和无效输入调用方法的测试,并使测试确认结果与你认为会发生的结果相符。
这是一个简短且不完整的描述,请在Wikipedia和junit.org详细了解。
以下是JUnit in Eclipse的旧版(2005年)工作指南。