eclipse 为 Junit 测试编写测试用例
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3398504/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Writing test case for Junit testing
提问by Global Dictator
As a developer, I'm a newbie to Unit testing and have a requirement to write a test case to unit test the following code. Could somebody help me here and also give me some pointers on how to write unit tests in eclipse.
作为开发人员,我是单元测试的新手,并且需要编写测试用例来对以下代码进行单元测试。有人可以在这里帮助我,并就如何在 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());
}
}
Thanks
谢谢
Update
更新
For some reason when I running the test case, I'm not getting any coverage at all. Am I doing something wrong here?? Further researching suggests that I need to use test.perform() method to call the method I want to test.. Is that correct?? Can you please suggest something?? Here is the code:
出于某种原因,当我运行测试用例时,我根本没有得到任何覆盖。我在这里做错了吗??进一步的研究表明我需要使用 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);
}
}
The decorate(JtextComponent jComponent)
method is present in the class to be tested (MaxLength
) and is defined as :
该decorate(JtextComponent jComponent)
方法存在于要测试的类中 ( MaxLength
) 并定义为:
public final void decorate(final JTextComponent c) {
//TODO throw exception if already decorating
this.component = c;
component.getDocument().addDocumentListener(this);
}
#
UPDATE:
更新:
@Peter: Managed to find out that it is not the Component class that is the problem but instead I needed asm (http://forge.ow2.org/projects/asm). I've also change the code to combine the 2 methods into 1 method:
@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);
}
But now I'm having a different error on verify:
但是现在我在验证时遇到了不同的错误:
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)
This is caused when executing EasyMock.verify() statement on mockComponent.
这是在 mockComponent 上执行 EasyMock.verify() 语句时引起的。
回答by Péter T?r?k
I recommend using a mocking framework, such as EasyMock. Mocks allow you to configure dependencies with the desired behaviour for your tests. In your case, you need a mock DocumentEvent
and ideally another one for component
, which I guess is a class member.
我建议使用模拟框架,例如EasyMock。模拟允许您为测试配置具有所需行为的依赖项。在您的情况下,您需要一个模拟DocumentEvent
,最好是另一个 for component
,我猜它是班级成员。
The two aspects to unit testing
单元测试的两个方面
- howto test, i.;e. the technical details of assembling the right set of objects in the right state required for the test to run properly (aka the _test fixture), and
- whatto test, i.e. the scenarios to validate.
- 如何测试,即 在测试正常运行所需的正确状态下组装正确对象集的技术细节(又名 _test 固定装置),以及
- 要测试什么,即要验证的场景。
How to test
如何测试
Eclipse supports JUnit out of the box, so you may quickly generate new JUnit testcases (in Project Explorer context menu: New -> (Other ->) JUnit -> JUnit Test Case), then run it by clicking on the Run button.
Eclipse 支持开箱即用的 JUnit,因此您可以快速生成新的 JUnit 测试用例(在 Project Explorer 上下文菜单中:New -> (Other ->) JUnit -> JUnit Test Case),然后通过单击 Run 按钮运行它。
Setting up the test fixture in your case would look something like this, using EasyMock (and assuming you can pass the component as a constructor parameter to your tested class):
在您的案例中设置测试装置看起来像这样,使用 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);
}
This test assumes that maxMessageSize
is at least 1 by default - setting maxMessageSize
up for the test is left to you as an exercise as the code snippet you published gives no clue for that.
此测试假定maxMessageSize
默认情况下至少为 1 -maxMessageSize
测试设置留给您作为练习,因为您发布的代码片段没有提供任何线索。
What to test
测试什么
The method you show gets text from the document associated with the event, then based on its length, it does different things. I would write at least the following unit tests for this:
您显示的方法从与事件关联的文档中获取文本,然后根据其长度,它会做不同的事情。我至少会为此编写以下单元测试:
- empty document text with
maxMessageSize == 0
- empty document text with
maxMessageSize > 0
- nonempty document text with
maxMessageSize == text.length()
- nonempty document text with
maxMessageSize > text.length()
- nonempty document text with
maxMessageSize < text.length()
andaddHighlight()
throwingBadLocationException
- 空文档文本
maxMessageSize == 0
- 空文档文本
maxMessageSize > 0
- 非空文档文本
maxMessageSize == text.length()
- 非空文档文本
maxMessageSize > text.length()
- 带有
maxMessageSize < text.length()
和addHighlight()
抛出的非空文档文本BadLocationException
Notes
笔记
- sensing the
BadLocationException
is a bit tricky, since all it produces is an output to stdout; luckily, you can easily reassign stdout via System.setOut. However, you may want to consider improving exception handling, at least by using a logging framework instead of printing to stdout. - from the code it seems that other methods (such as
removeAllHighlights()
and/orgetText()
) may also throwBadLocationException
, however thetry-catch
blocks are not well organized. I would consider adding more unit tests where those methods throw, and after that, refactoring the exception handling code.
- 检测
BadLocationException
有点棘手,因为它产生的只是输出到标准输出;幸运的是,您可以通过System.setOut轻松地重新分配标准输出。但是,您可能需要考虑改进异常处理,至少通过使用日志记录框架而不是打印到标准输出。 - 从代码看来,其他方法(例如
removeAllHighlights()
和/或getText()
)也可能会抛出BadLocationException
,但是这些try-catch
块组织得不好。我会考虑在这些方法抛出的地方添加更多单元测试,然后重构异常处理代码。
Update
更新
I thought there was something wrong that I was doing...Can you please provide me with the modified/corrected code please???
我以为我做错了什么......你能向我提供修改/更正的代码吗???
Your testSetLength
method is not really testing anything - you need assert statements (and/or EasyMock verification) in order for your unit tests to actually verify some behaviour. However, it provides the missing clue for setting up the tested class. So I try to unify your two test methods to create one which is hopefully working (I am writing from memory, so I can't guarantee it will all compile and run perfectly at first try) :
您的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);
}
回答by Peter Jaric
When you write a unit test, you try to test if (in this case) the method does what it is supposed to do. You should notlook at the implementation and write your test from that. Instead, you should think about what inputs the method should be able to handle, and what should be the result (returned value and/or side effects) after the method has been called.
当您编写单元测试时,您会尝试测试(在这种情况下)该方法是否执行了它应该执行的操作。你应该不看执行和写入您的测试。相反,您应该考虑该方法应该能够处理哪些输入,以及调用该方法后的结果(返回值和/或副作用)应该是什么。
Then you should write one or more tests that calls the method with valid and and invalid inputs and make the test confirm that the results matched what you thought would happen.
然后,您应该编写一个或多个测试,使用有效和无效的输入调用该方法,并使测试确认结果与您认为会发生的情况相符。
This was a short and incomplete description, read more at Wikipediaand junit.org.
这是一个简短且不完整的描述,请在Wikipedia和junit.org阅读更多内容。
Here is an old (2005) but working guide to JUnit in Eclipse.
这是Eclipse 中 JUnit的旧(2005)但工作指南。