Как проверить абстрактный class на Java с помощью JUnit?

Я новичок в тестировании Java с помощью JUnit. Я должен работать с Java, и я хотел бы использовать модульные тесты.

Моя проблема: у меня есть абстрактный class с некоторыми абстрактными методами. Но есть некоторые методы, которые не абстрактны. Как проверить этот class с помощью JUnit? Пример кода (очень простой):

abstract class Car { public Car(int speed, int fuel) { this.speed = speed; this.fuel = fuel; } private int speed; private int fuel; abstract void drive(); public int getSpeed() { return this.speed; } public int getFuel() { return this.fuel; } } 

Я хочу проверить функции getSpeed() и getFuel() .

Подобный вопрос к этой проблеме здесь , но он не использует JUnit.

В разделе FAQ JUnit я нашел эту ссылку , но я не понимаю, что автор хочет сказать в этом примере. Что означает эта строка кода?

 public abstract Source getSource() ; 

Если у вас нет конкретных реализаций classа, и методы не static зачем их тестировать? Если у вас есть конкретный class, вы будете тестировать эти методы как часть общедоступного API конкретного classа.

Я знаю, что вы думаете: «Я не хочу тестировать эти методы снова и снова, потому что я создал абстрактный class», но мой аргумент счетчика заключается в том, что точка модульных тестов позволяет разработчикам вносить изменения, провести тесты и проанализировать результаты. Часть этих изменений может включать переопределение методов абстрактного classа, как protected и public , что может привести к фундаментальным изменениям в поведении. В зависимости от характера этих изменений это может повлиять на то, как ваше приложение запускается неожиданными, возможно, негативными способами. Если у вас есть хороший набор модhive тестирования, проблемы, связанные с этими изменениями, должны проявляться во время разработки.

Создайте конкретный class, который наследует абстрактный class, а затем проверит функции, которые наследует конкретный class из абстрактного classа.

С classом classа, который вы опубликовали, кажется, не имеет смысла тестировать getFuel() и getSpeed() поскольку они могут возвращать только 0 (нет сеттеров).

Однако, предполагая, что это был просто упрощенный пример для иллюстративных целей, и что у вас есть законные причины для тестирования методов в абстрактном базовом classе (другие уже указали на последствия), вы можете настроить свой тестовый код так, чтобы он создавал анонимный подclass базового classа, который просто предоставляет манекены (no-op) для абстрактных методов.

Например, в вашем TestCase вы можете сделать это:

 c = new Car() { void drive() { }; }; 

Затем проверьте остальные методы, например:

 public class CarTest extends TestCase { private Car c; public void setUp() { c = new Car() { void drive() { }; }; } public void testGetFuel() { assertEquals(c.getFuel(), 0); } [...] } 

(Этот пример основан на синтаксисе JUnit3. Для JUnit4 код будет немного отличаться, но идея такая же.)

Если вам все равно нужно решение (например, потому, что у вас слишком много реализаций абстрактного classа, и тестирование всегда повторяет одни и те же процедуры), тогда вы можете создать абстрактный тестовый class с абстрактным заводским методом, который будет исключен путем реализации этого испытательный class. Эти примеры работают или меня с TestNG:

Абстрактный class испытаний Car :

 abstract class CarTest { // the factory method abstract Car createCar(int speed, int fuel); // all test methods need to make use of the factory method to create the instance of a car @Test public void testGetSpeed() { Car car = createCar(33, 44); assertEquals(car.getSpeed(), 33); ... 

Реализация Car

 class ElectricCar extends Car { private final int batteryCapacity; public ElectricCar(int speed, int fuel, int batteryCapacity) { super(speed, fuel); this.batteryCapacity = batteryCapacity; } ... 

Единица испытания classа ElectricCarTest classа ElectricCar :

 class ElectricCarTest extends CarTest { // implementation of the abstract factory method Car createCar(int speed, int fuel) { return new ElectricCar(speed, fuel, 0); } // here you cann add specific test methods ... 

Вы могли бы сделать что-то вроде этого

 public abstract MyAbstractClass { @Autowire private MyMock myMock; protected String sayHello() { return myMock.getHello() + ", " + getName(); } public abstract String getName(); } // this is your JUnit test public class MyAbstractClassTest extends MyAbstractClass { @Mock private MyMock myMock; @InjectMocks private MyAbstractClass thiz = this; private String myName = null; @Override public String getName() { return myName; } @Test public void testSayHello() { myName = "Johnny" when(myMock.getHello()).thenReturn("Hello"); String result = sayHello(); assertEquals("Hello, Johnny", result); } } 

Вы можете создать экземпляр анонимного classа, а затем проверить этот class.

 public class ClassUnderTest_Test { private ClassUnderTest classUnderTest; private MyDependencyService myDependencyService; @Before public void setUp() throws Exception { this.myDependencyService = new MyDependencyService(); this.classUnderTest = getInstance(); } private ClassUnderTest getInstance() { return new ClassUnderTest() { private ClassUnderTest init( MyDependencyService myDependencyService ) { this.myDependencyService = myDependencyService; return this; } @Override protected void myMethodToTest() { return super.myMethodToTest(); } }.init(myDependencyService); } } 

Имейте в виду, что видимость должна быть protected для свойства myDependencyService абстрактного classа ClassUnderTest .

Вы также можете комбинировать этот подход с Mockito. См. Здесь .

Я бы создал подclass jUnit, который наследуется от абстрактного classа. Это можно создать и получить доступ ко всем методам, определенным в абстрактном classе.

Вы не можете протестировать весь абстрактный class. В этом случае у вас есть абстрактные методы, это означает, что они должны быть реализованы classом, который расширяет данный абстрактный class.

В этом classе программист должен написать исходный код, предназначенный для его логики.

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

Если у вас есть основная функциональность, не связанная с абстрактными методами в каком-то абстрактном classе, просто создайте еще один class, в котором абстрактный метод будет вызывать какое-то исключение.

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

Мой способ проверить это довольно просто, в пределах каждого abstractUnitTest.java . Я просто создаю class в abstractUnitTest.java, который расширяет абстрактный class. И протестируйте это так.

  • Тестирование API Java EE 6
  • Как высмеять окончательный class с mockito
  • Java: Является ли assertEquals (String, String) надежным?
  • Тестирование пустот методом JUNIT
  • Eclipse - отладчик не останавливается в точке останова
  • Как протестировать веб-сервис Джерси REST?
  • Как утверждать равенство на двух classах без метода equals?
  • В чем разница между ошибкой и ошибкой в ​​JUnit?
  • Легкий способ повторения одного и того же теста на юнитах снова и снова?
  • Как выполнить повторный запуск неудачных тестов JUnit?
  • Никаких тестов с тест-бегуном «JUnit 4»
  • Давайте будем гением компьютера.