Написание тестового примера для тестирования Junit - PullRequest
2 голосов
/ 03 августа 2010

Как разработчик, я новичок в модульном тестировании и должен написать тестовый пример для модульного тестирования следующего кода. Может ли кто-нибудь помочь мне здесь, а также дать мне несколько советов о том, как писать модульные тесты в затмении.

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

ОБНОВЛЕНИЕ:

@ Питер: Удалось выяснить, что проблема не в классе 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)

Это вызывается при выполнении оператора EasyMock.verify () для mockComponent.

Ответы [ 2 ]

10 голосов
/ 03 августа 2010

Я рекомендую использовать фреймворк , например EasyMock .Mocks позволяют вам настроить зависимости с желаемым поведением для ваших тестов.В вашем случае вам нужен макет DocumentEvent и в идеале еще один для component, который, я думаю, является членом класса.

Два аспекта модульного тестирования

  • как проверить, т. Е.технические детали сборки правильного набора объектов в нужном состоянии, необходимые для правильной работы теста (он же прибор _test), и
  • что проверить, то есть сценарии для проверки.

Как тестировать

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 up для теста оставлена ​​вам в качестве упражнения в качестве фрагмента кодаВы опубликовали, не дает подсказки для этого.

Что тестировать

Метод, который вы показываете, получает текст из документа, связанного с событием, а затем на основе его длины, он делаетразные вещи.Я бы написал для этого как минимум следующие юнит-тесты:

  • пустой текст документа с maxMessageSize == 0
  • пустой текст документа с maxMessageSize > 0
  • непустой текст документас maxMessageSize == text.length()
  • непустым текстом документа с maxMessageSize > text.length()
  • непустым текстом документа с maxMessageSize < text.length() и addHighlight() выбрасыванием BadLocationException

Примечания

  1. воспринимать BadLocationException немного сложно, поскольку все, что он производит, это вывод в stdout;К счастью, вы можете легко переназначить стандартный вывод через System.setOut .Тем не менее, вы можете рассмотреть возможность улучшения обработки исключений, по крайней мере, с помощью каркаса ведения журнала вместо печати в стандартный вывод.
  2. из кода кажется, что другие методы (такие как removeAllHighlights() и / или getText()) также может выдавать BadLocationException, однако блоки try-catch не очень хорошо организованы.Я хотел бы рассмотреть возможность добавления дополнительных модульных тестов, где эти методы выдают, и после этого рефакторинг кода обработки исключений.

Обновление

Я думал, что что-то не так, что я былделать ... Можете ли вы предоставить мне измененный / исправленный код, пожалуйста ???

Ваш testSetLength метод на самом деле ничего не тестирует - вам нужны операторы assert (и / или проверка 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); 
  }
4 голосов
/ 03 августа 2010

Когда вы пишете модульный тест, вы пытаетесь проверить, выполняет ли (в этом случае) метод то, что он должен делать. Вы должны не посмотреть на реализацию и написать свой тест из этого. Вместо этого вам следует подумать о том, какие входные данные должен обрабатывать метод и каким должен быть результат (возвращаемое значение и / или побочные эффекты) после вызова метода.

Затем вы должны написать один или несколько тестов, которые вызывают метод с допустимыми и недействительными входными данными, и сделать так, чтобы тест подтвердил, что результаты соответствуют ожидаемым.

Это было краткое и неполное описание, подробнее на Википедии и junit.org .

Вот старое (2005), но рабочее руководство по JUnit в Eclipse .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...