Я написал несколько классов, которые должны быть неизменяемыми. Я пытаюсь их проверить. Я, конечно, могу использовать МобильностьДетектор, но я хочу написать что-нибудь самостоятельно. Не обширное, что-то базовое
Идея, которую я пытаюсь реализовать в своих тестовых примерах, заключается в том, что для каждого действия ссылка на объект для объекта, который я выполнил действие, будет отличаться от объекта, возвращенного из действия.
Например, предположим, что я разработал класс, скажем, Digit, и у него есть метод под названием add. Итак, тестовый пример, который я пишу,
@Test
public void test_add(){
Digit zero = Digit.getInstance(); //ignore why i am using getinstance here
Digit result = zero.add(new Random().nextInt());
assertNotEqual (zero, result); //there is no equal method overridden in Digit class
}
Я предполагаю, что assertNotEqual проверит Справка двух объектов (zero и result). Если обе ссылки различны, это означает, что операция, выполненная с объектом zero, вернула новый объект, а не старый.
Имеет ли это смысл?
@markspace благодарит за вклад. Возможно, я не смогу поделиться исходным кодом, поскольку он связан с заданием, над которым я работаю. Фактический код касается реализации структуры данных и их основных операций. @StephenC - конечно, вместо использования equals я могу просто использовать оператор ==. Но вопрос остается прежним. это правильный подход к проверке неизменяемости.
Не используйте случайность в модульном тесте. Нет никакой ценности. Используйте константы.




My assumption here is that assertNotEqual will test the reference of two objects
Не предполагайте. Прочтите javadoc! Он говорит:
Asserts that two objects are not equals. If they are, an AssertionError without a message is thrown. If unexpected and actual are null, they are considered equal.
Другими словами, это использование стандартного метода проверки равенства Object::equals(Object). Это будет использовать сравнение == только в том случае, если это то, что делает соответствующий метод equals(Object) под капотом.
Чтобы ответить на ваш вопрос, тестирование zero == result не является ни необходимым, ни достаточным тестом на неизменность.
zero плюс какое-то случайное целое число может быть нулемzero - это == или не == - result, не доказывает, что состояние объекта zero не изменилось.На самом деле, я не думаю, что существует действительный тест на неизменяемость в общем смысле. Свойство неизменяемости описывает то, что происходит внутри границы абстракции вашего класса Digit. Если вы относитесь к Digit как к истинному черному ящику, вы не можете предполагать, что сможете обнаружить изменения внутри ящика.
Единственный действенный способ проверить (истинную) неизменяемость - это объединить тестирование с (уверенным) знанием того, что происходит «внутри коробки»; т.е. проверка кода вашего класса Digit и тестирование методом белого ящика.
Другой альтернативный вариант - определить, что вы подразумеваете под «неизменяемостью» в терминах определенных внешне видимых атрибутов Digit; например что возвращает toString(). (Но с этим подходом тоже есть проблемы ...)
как бы вы в этом случае проводили тестирование методом белого ящика?
Я бы начал с рассмотрения класса Digit.
assertEquals / assertNotEquals проверка на равенство с использованием метода объектов equals. Он похож на assertTrue(expected.equals(actual)). Если равенство не переопределено, он проверит ссылки на объект (хэш-код), но я бы не стал на это полагаться, поскольку это может нарушить ваш тест, если вы в конечном итоге реализуете метод equals.
Если вы хотите проверить, совпадают ли объекты (или нет), используйте assertSame / assertNoSame, которые проверяют на равенство ссылок, аналогично assertTrue(expected == actual).
Но проверка неизменяемости - это не только проверка того, возвращает ли какая-либо модифицирующая операция новый экземпляр, но и проверка того, что исходный объект все еще не изменился!
Один из способов сделать это - создать эталонный объект (или клон) исходного объекта и Кроме того проверить, что исходный объект все еще равен эталонному объекту после вызова add.
@Test
public void test_add(){
Digit zero = Digit.getInstance();
Digit goldenMaster = zero.clone(); //if clone is implemented
//or this
Digit goldenMaster = Digit.getInstance();
Digit result = zero.add(new Random().nextInt());
assertNotSame (zero, result); //use check for reference
assertEquals(goldenMaster, zero); //check the original object is still unmodified
}
Но это, в свою очередь, требует, чтобы вы правильно реализовали равенство.
1. Лично, если ваши методы настолько просты, я бы не стал их тестировать. Реальный пример может помочь. 2. Если
nextInt()возвращает 0, может быть, нецелесообразно возвращать исходный объект? Я думаю, что этот тест может быть подвержен периодическим сбоям.