JUnit으로 Java 테스트를 처음 사용합니다. Java로 작업해야하고 단위 테스트를 사용하고 싶습니다.
내 문제는 : 일부 추상 메서드가있는 추상 클래스가 있습니다. 그러나 추상적이지 않은 방법이 있습니다. 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을 사용하지 않습니다.
JUnit FAQ 섹션 에서이 링크를 찾았 지만 저자가이 예제에서 무엇을 말하고 싶어하는지 이해하지 못합니다. 이 코드 줄은 무엇을 의미합니까?
public abstract Source getSource() ;
답변
클래스의 구체적인 구현이없고 메서드가 static
테스트의 요점 이 아니라면 ? 구체적인 클래스가있는 경우 해당 메서드를 구체적인 클래스의 공용 API의 일부로 테스트하게됩니다.
나는 당신이 “내가 추상 클래스를 만든 이유 때문에이 메소드들을 계속해서 테스트하고 싶지 않다”라고 생각하는 것을 알고 있지만, 이에 대한 내 반론은 단위 테스트의 요점이 개발자가 변경할 수 있도록하는 것입니다. 테스트를 실행하고 결과를 분석합니다. 이러한 변화의 일부는 추상 클래스의 메소드를 오버라이드 (override) 포함, 모두 수 protected
및 public
근본적인 행동 변화를 초래할 수있는. 이러한 변경의 특성에 따라 응용 프로그램이 예상치 못한 방식으로 실행되는 방식에 영향을 미칠 수 있습니다. 좋은 단위 테스트 스위트가 있다면 이러한 유형 변경으로 인해 발생하는 문제는 개발시 명백해야합니다.
답변
추상 클래스를 상속하는 구체적인 클래스를 만든 다음 해당 추상 클래스에서 상속되는 함수를 테스트합니다.
답변
게시 한 예제 클래스를 사용하면 테스트하는 것이별로 의미가없는 것 같 getFuel()
으며 getSpeed()
0 (세터가 없음) 만 반환 할 수 있기 때문입니다.
그러나 이것이 설명을위한 단순한 예제 일 뿐이고 추상 기본 클래스에서 메서드를 테스트 할 합법적 인 이유가 있다고 가정하면 (다른 사람들은 이미 의미를 지적 했음) 익명을 생성하도록 테스트 코드를 설정할 수 있습니다. 추상 메서드에 대한 더미 (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의 경우 코드가 약간 다르지만 아이디어는 동일합니다.)
답변
어쨌든 솔루션이 필요한 경우 (예 : 추상 클래스의 구현이 너무 많고 테스트가 항상 동일한 절차를 반복하기 때문에) 해당 구현에 의해 실행되는 추상 팩토리 메서드로 추상 테스트 클래스를 만들 수 있습니다. 테스트 클래스. 이 예제는 TestNG와 함께 작동합니다.
의 추상 테스트 클래스 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;
}
...
클래스 ElectricCarTest
의 단위 테스트 클래스 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);
}
}
답변
추상 클래스에서 상속하는 jUnit 내부 클래스를 만듭니다. 이것은 인스턴스화 될 수 있으며 추상 클래스에 정의 된 모든 메소드에 액세스 할 수 있습니다.
public class AbstractClassTest {
public void testMethod() {
...
}
}
class ConcreteClass extends AbstractClass {
}
답변
익명 클래스를 인스턴스화 한 다음 해당 클래스를 테스트 할 수 있습니다.
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
에 대한 것이 어야합니다 ClassUnderTest
.
이 접근 방식을 Mockito와 깔끔하게 결합 할 수도 있습니다. 를 참조하십시오 여기 .