HashSet в модульных тестах - PullRequest
       20

HashSet в модульных тестах

5 голосов
/ 12 августа 2011

У меня есть несколько методов, возвращающих HashSet.Я хотел бы, чтобы мой модульный тест проверил состояние этих объектов, т.е. подтвердил, что someObject.getName() == "foobar".

Однако порядок итераторов в хэш-наборе не гарантирован, поэтому мои модульные тесты не всегда выполняются.Как мне написать модульные тесты для чего-то подобного?

Например:

@Test
    public void testRowsToBeRead(){
        HashSet<SomeObject> rows = new SomeObject().read();
        assertEquals(19, rows.size());

        for(SomeObject r:rows){
            //How do I confirm contents?
        }
    }

Мне кажется, я мог бы принять ответ слишком рано.

Проблема, с которой я столкнулсяявляется то, что я реализовал метод equals, который проверяет только 2 поля в объекте на дизайн (он имитирует таблицу БД).Однако в моем модульном тесте я хочу проверить все поля, такие как описание и т. Д., Которые не находятся в моих равных.Таким образом, если 2 из полей поменялись местами, и эти поля не находятся в моей реализации equals, тогда модульный тест дает ложное срабатывание.

Ответы [ 5 ]

4 голосов
/ 12 августа 2011

Мой подход:

public void testRowsToBeRead(){
    HashSet<SomeObject> expectedRows = new HasSet<SomeObject();
    expectedRows.add(new SomeObject("abc"));
    expectedRows.add(new SomeObject("def"));

    HashSet<SomeObject> rows = new SomeObject().read();

    // alternative 1
    assertEquals(19, rows.size());

    for(SomeObject r:rows){
        if (!expectedRows.contains(r)) {
            // test failed
        }
    }

    // alternative 2
    assertTrue(expectedRows.equals(rows));
}

Чтобы полагаться на этот тест, вам могут потребоваться другие модульные тесты, подтверждающие, что SomeObject equals и hashCode методы работают так, как и должно быть ...

РЕДАКТИРОВАТЬ на основе одного из ваших комментариев

Если вы хотите проверить поля, не входящие в equals контракт, вам нужно выполнить итерацию по набору:

public void testRowsToBeRead(){
    HashSet<SomeObject> expectedRows = new HasSet<SomeObject();
    expectedRows.add(new SomeObject("a", "a1"));
    expectedRows.add(new SomeObject("b", "b1"));

    HashSet<SomeObject> rows = new SomeObject().read();

    for(SomeObject r : rows) {
        SomeObject expected = expectedRows.get(r); // equals and hashCode must still match

        if (expected == null) {
            // failed
        }

        if (!expected.getField1().equals(r.getField1()) && !expected.getField2().equals(r.getField2())) {
            // failed
        }
    }
}

В приведенном выше примере SomeObject equals может выглядеть следующим образом, он проверяет только на field1:

@Override
public boolean equals(Object other) {
    return this.getField1().equals( ((SomeObject) other).getField1() );
}

Без вопросов, в зависимости от конкретного варианта использованияэто может стать более сложным.Надеюсь, это поможет ...

2 голосов
/ 13 августа 2011

Вы можете использовать Assert.assertEquals () практически для любой коллекции с TestNG и, возможно, также с JUnit.

Если вы хотите выполнить это самостоятельно, удалите все элементы фактического набора из ожидаемого набораи утверждать, что размер ожидаемого набора равен нулю, когда вы закончите.

2 голосов
/ 12 августа 2011

Попробуйте использовать assertThat:

Assert.assertThat(r.getName(), AnyOf.anyOf(Is.is("foobar1"), Is.is("foobar2"), ...));
2 голосов
/ 12 августа 2011

Вы можете использовать LinkedHashSet, который гарантирует заказ.

0 голосов
/ 13 августа 2011

Я рекомендую использовать HashSet.equals(Object).

JavaDoc говорит:

Эта реализация сначала проверяет, является ли указанный объект этим набором;если это так, он возвращает истину.Затем он проверяет, является ли указанный объект набором, размер которого идентичен размеру этого набора;если нет, возвращается false.Если это так, он возвращает значение содержитAll ((Коллекция) o).

Так что я думаю, что «альтернативы 2» для home достаточно.гарантировать порядок, равные HashSets находятся в том же порядке и размере.

...