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.
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:
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 :
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:
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.
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
DocumentEventand ideally another one forcomponent, which I guess is a class member.The two aspects to unit testing
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.
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):
This test assumes that
maxMessageSizeis at least 1 by default – settingmaxMessageSizeup for the test is left to you as an exercise as the code snippet you published gives no clue for that.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:
maxMessageSize == 0maxMessageSize > 0maxMessageSize == text.length()maxMessageSize > text.length()maxMessageSize < text.length()andaddHighlight()throwingBadLocationExceptionNotes
BadLocationExceptionis 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.removeAllHighlights()and/orgetText()) may also throwBadLocationException, however thetry-catchblocks are not well organized. I would consider adding more unit tests where those methods throw, and after that, refactoring the exception handling code.Update
Your
testSetLengthmethod 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) :