JVM

JUnit

kyoulho 2024. 7. 28. 13:13

JUnit은 JVM 생태계에서 가장 널리 사용되는 테스트 프레임워크로, 주로 단위 테스트를 위한 도구를 제공하지만, 통합 테스트에도 활용할 수 있다.

JUnit의 주요 특징은 어노테이션 기반 테스트 지원, 단정문(Assert)을 통한 테스트 결과 검증이 있다.

통합 테스트
여러 컴포넌트를 조합하여 전체 비즈니스 로직을 검증한다. @SpringBootTest를 주로 사용하지만, 대규모 프로젝트에서는 실행 시간이 길어질 수 있다.
단위 테스트
단위 테스트는 코드의 특정 모듈이 의도한 대로 동작하는지 각 함수와 메소드에 대한 개별 테스트 케이스를 작성하여 검증합니다.

FIRST 원칙
효과적인 단위 테스트를 위한 5가지 원칙을 FIRST 원칙이라고 한다.
Fast: 테스트는 빠르게 실행되어야 한다.
Independent: 각 테스트는 독립적이어야 한다.
Repeatable: 테스트는 항상 동일한 결과를 produce해야 한다.
Self-Validating: 테스트는 자체적으로 결과를 검증할 수 있어야 한다.
Timely: 테스트는 프로덕션 코드 작성 전이나 동시에 작성되어야 한다.

 

JUnit 5의 구조


JUnit 5는 주로 세 가지 주요 모듈로 구성되지만, 실제로는 다양한 하위 모듈로 구성되어 있어 더 많은 기능을 제공한다.

JUnit Jupiter

JUnit Jupiter는 JUnit 5에서 새로 도입된 프로그래밍 및 확장 모델을 정의한다. Jupiter는 다음과 같은 하위 모듈로 구성된다.

모듈 설명
junit-jupiter-api JUnit Jupiter API는 테스트를 작성하는 데 사용되는 애노테이션과 인터페이스를 제공한다.
예를 들어, @Test, @BeforeEach, @AfterEach 등이 포함된다.
junit-jupiter-engine JUnit Jupiter로 작성된 테스트를 발견하고 실행하는 런타임 컴포넌트이다.
junit-jupiter-params 다양한  파라미터를 사용하여 동일한 테스트 메서드를 여러 번 실행할 수 있도록 지원한다.
csv 파일이나 Java Stream을 사용하여 파라미터화된 테스트를 실행할 수 있다.

JUnit Platform

JUnit Platform은 JUnit 5에서 테스트를 발견하고 실행하기 위한 기반 역할을 한다. Platform은 다음과 같은 하위 모듈로 구성된다.

모듈 설명
junit-platform-commons JUnit Platform에서 공통으로 사용하는 유틸리티와 헬퍼 클래스, 내부 기능을 제공한다.
junit-platform-engine 테스트 엔진을 정의하고 구현하기 위한 인터페이스를 제공한다.
junit-platform-launcher 테스트를 발견하고 실행하는 런처이다.
다양한 테스트 엔진을 통합하여 사용할 수 있다.
junit-platform-reporting 테스트 실행 결과를 보고하는 기능을 제공한다.
결과를 콘솔에 출력하거나 파일로 저장할 수 있다.
junit-platform-suite-api 다양한 테스트 클래스를 하나의 스위트로 묶어 실행할 수 있는 API를 제공한다.
junit-platform-runner JUnit 4 테스트 러너를 사용하여 JUnit 5 테스트를 실행할 수 있도록 한다.
junit-platform-surefire-provider Apache Maven Surefire 플러그인과 통합되어 JUnit 5 테스트를 실행하는 데 사용된다.
junit-platform-console-standalone 독립 실행형 모드로 JUnit 5 테스트를 실행할 수 있는 콘솔 애플리케이션이다.
명령줄에서 직접 테스트를 실행하고 결과를 볼 수 있다.

JUnit Vintage

JUnit Vintage는 JUnit 3과 JUnit 4로 작성된 테스트를 JUnit 5 환경에서 실행할 수 있도록 지원한다. 다음과 같은 하위 모듈로 구성된다

모듈 설명
junit-vintage-engine Unit 3과 JUnit 4로 작성된 기존 테스트를 JUnit 5 환경에서 실행할 수 있도록 지원한다.
기존 코드를 수정하지 않고도 JUnit 5로 마이그레이션할 수 있게 해준다.

 

 

JUnit 애노테이션


Spring Boot 테스트 애노테이션

@SpringBootTest

@SpringBootTest는 통합 테스트를 실행하기 위해 전체 Spring 애플리케이션 컨텍스트를 로드한다. 모든 빈이 로드되며, 실제 애플리케이션 환경에서 테스트가 실행된다.

@SpringBootTest
class MyApplicationTests {
    @Test
    void contextLoads() {
        // 테스트 코드
    }
}

@WebMvcTest

@WebMvcTest는 웹 레이어(컨트롤러와 관련된 부분)만 테스트하기 위해 사용된다. 보통 Spring MVC 컨트롤러 테스트에 사용되며, 서비스나 리포지토리는 목(mock)으로 처리해야 한다.

@WebMvcTest(MyController.class)
class MyControllerTests {
    @Autowired
    private MockMvc mockMvc;
    
    @Test
    void testController() throws Exception {
        mockMvc.perform(get("/endpoint"))
               .andExpect(status().isOk());
    }
}

@DataJpaTest

@DataJpaTest는 JPA 리포지토리 레이어만 테스트하기 위해 사용된다. 데이터베이스와의 상호작용을 테스트하며, 일반적으로 내장형 데이터베이스를 사용한다.

기본적으로 테스트 메서드마다 트랜잭션을 열고, 메서드가 종료되면 자동으로 롤백한다.

@DataJpaTest
class MyRepositoryTests {
    @Autowired
    private MyRepository myRepository;
    
    @Test
    void testFindByName() {
        // 리포지토리 테스트 코드
    }
}

@RestClientTest

@RestClientTest는 REST 클라이언트를 테스트하기 위해 사용된다. RestTemplate이나 WebClient를 사용하여 외부 API와 상호작용하는 코드를 테스트한다.

@RestClientTest(MyService.class)
class MyServiceTests {
    @Autowired
    private MyService myService;
    
    @Test
    void testRestClient() {
        // REST 클라이언트 테스트 코드
    }
}

@AutoConfigureMockMvc

@AutoConfigureMockMvc는 @SpringBootTest와 함께 사용하여 MockMvc를 자동 구성한다. 주로 전체 애플리케이션 컨텍스트를 로드하지 않고도 컨트롤러 테스트를 수행할 때 사용된다.

@SpringBootTest
@AutoConfigureMockMvc
class MyApplicationTests {
    @Autowired
    private MockMvc mockMvc;
    
    @Test
    void testEndpoint() throws Exception {
        mockMvc.perform(get("/endpoint"))
               .andExpect(status().isOk());
    }
}

@ContextConfiguration

테스트의 ApplicationContext를 설정하는 데 사용된다. 클래스나 XML 파일을 통해 설정을 로드할 수 있다. 다양한 컨텍스트 설정 파일을 로드하거나 특정 설정 클래스를 지정하여 컨텍스트를 설정할 때 사용된다.

@ContextConfiguration(classes = TestConfig.class)
class MyTests {
    @Autowired
    private MyService myService;

    @Test
    void testService() {
        // myService가 TestConfig에 의해 설정됨
    }
}

@ContextConfiguration(locations = "classpath:app-config.xml")
class MyTests {
    @Autowired
    private MyService myService;

    @Test
    void testService() {
        // myService가 app-config.xml에 의해 설정됨
    }
}

@Import

하나 이상의 @Configuration 클래스를 현재 테스트 클래스의 컨텍스트에 가져온다.  주로 특정 구성 클래스만을 가져와 테스트 환경을 설정하고자 할 때 사용된다. 예를 들어, 테스트 중 특정 빈을 정의하거나 설정을 커스터마이즈 할 때 유용하다.

@Configuration
class TestConfig {
    @Bean
    public MyService myService() {
        return new MyServiceImpl();
    }
}

@SpringBootTest
@Import(TestConfig.class)
class MyTests {
    @Autowired
    private MyService myService;

    @Test
    void testService() {
        // myService가 TestConfig에 의해 설정됨
    }
}

@SpringJUnitConfig

@SpringJUnitConfig는 @ExtendWith(SpringExtension.class)와 @ContextConfiguration을 조합한 애노테이션이다. JUnit 5와 함께 Spring 컨텍스트를 설정한다.

@SpringJUnitConfig(MyConfig.class)
class MyTests {
    @Autowired
    private MyService myService;
    
    @Test
    void testService() {
        // 서비스 테스트 코드
    }
}

@TestConfiguration

테스트 전용 @Configuration 클래스를 정의할 때 사용된다. 보통 내부 클래스로 정의되어, 테스트 범위 내에서만 사용된다. 테스트에 필요한 설정을 분리하여 정의할 때 사용된다.

@SpringBootTest
class MyTests {
    @TestConfiguration
    static class MyTestConfig {
        @Bean
        public MyService myService() {
            return new MyServiceImpl();
        }
    }
    
    @Autowired
    private MyService myService;
    
    @Test
    void testService() {
        // 서비스 테스트 코드
    }
}

@ActiveProfiles

@ActiveProfiles는 테스트 실행 시 활성화할 Spring 프로파일을 지정한다. 특정 프로파일에 따른 빈 설정을 테스트할 수 있다.

@ActiveProfiles("test")
@SpringBootTest
class MyTests {
    @Autowired
    private MyService myService;
    
    @Test
    void testService() {
        // 서비스 테스트 코드
    }
}

@Sql

테스트 메소드나 클래스가 실행되기 전에 SQL 스크립트를 실행하거나, 실행 후에 SQL 스크립트를 실행하도록 지정할 수 있다.  데이터베이스 초기화, 테스트 데이터 삽입, 또는 테스트 후 클린업 작업을 위해 사용한다.

@SpringBootTest
@Sql(scripts = "/test-schema.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
@Sql(scripts = "/test-data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
public class SomeRepositoryTests {
    @Autowired
    private SomeRepository repository;

    @Test
    void testFindById() {
        SomeEntity entity = repository.findById(1L).orElse(null);
        assertNotNull(entity);
    }
}

 

확장 애노테이션

@ExtendWith

JUnit5에서 확장 메커니즘을 제공하여, 테스트 클래스에 특정 동작을 추가할 수 있다. 특히, 스프링과의 통합을 위해 SpringExtension을 사용할 수 있다.

// JUnit5와 스프링을 통합하고 스프링의 의존성 주입을 테스트에서 사용할 수 있게 해준다.
@ExtendWith(SpringExtension.class)
public class SomeSpringTests {
    @Autowired
    private SomeService service;

    @Test
    void testService() {
        assertNotNull(service);
    }
}

// Mockito를 사용한 단위 테스트에 사용된다.
@ExtendWith(MockitoExtension.class)
public class SomeMockitoTests {
    @Mock
    private SomeService service;

    @InjectMocks
    private SomeController controller;

    @Test
    void testController() {
        when(service.someMethod()).thenReturn("expected");
        String response = controller.someEndpoint();
        assertEquals("expected", response);
    }
}
SpringBootTest와 @ExtendWith의 차이점
컨텍스트 로딩
@SpringBootTest는 전체 애플리케이션 컨텍스트를 로드한다.
이는 모든 빈을 초기화하고, 실제 애플리케이션처럼 동작하게 한다.
테스트 실행 속도
@SpringBootTest는 전체 컨텍스트를 로드하기 때문에 상대적으로 더 느리다.
@ExtendWith를 사용한 테스트는 필요한 부분만 로드하므로 더 빠르게 실행된다.
테스트 격리성
@SpringBootTest는 전체 컨텍스트를 로드하여 여러 테스트가 동일한 환경을 공유할 수 있다.
@ExtendWith는 필요한 빈만 로드하므로 테스트 간의 격리성이 높아진다.

@DirtiesContext

테스트 실행 후에 애플리케이션 컨텍스트를 "더럽혀진" 것으로 표시하고, 이후의 테스트에서 동일한 컨텍스트를 재사용하지 않도록 한다. 특정 테스트가 애플리케이션 컨텍스트의 상태를 변경하여 다른 테스트에 영향을 미칠 가능성이 있을 때 사용된다. 이 애노테이션을 사용하면, 해당 테스트가 실행된 후 컨텍스트가 재설정되거나 다시 로드된다.

테스트 클래스에 적용하면, 클래스 내의 모든 테스트가 실행된 후 컨텍스트가 더럽혀진 것으로 간주되고 특정 테스트 메소드에 적용하면, 해당 메소드가 실행된 후에만 컨텍스트가 더럽혀진 것으로 간주된다.

@SpringBootTest
class MyTests {

    @Autowired
    private MyService myService;

    @Test
    @DirtiesContext
    void testThatModifiesContext() {
        myService.modifyContext();
        // 이 테스트가 끝난 후 컨텍스트는 더럽혀진 것으로 표시되고 다시 로드된다.
    }

    @Test
    void anotherTest() {
        // 이 테스트는 새로운 컨텍스트에서 실행된다.
    }
}

 

 

기본 애노테이션

애노테이션 설명
@Test 단순히 테스트 메소드임을 나타냄. JUnit은 이 애노테이션이 붙은 메소드를 테스트 메소드로 인식.
@BeforeEach 각 테스트 메소드가 실행되기 전에 실행. 주로 테스트 준비 작업에 사용.
@AfterEach 각 테스트 메소드가 실행된 후에 실행. 주로 테스트 준비 작업에 사용.
@BeforeAll 모든 테스트 메소드가 실행되기 전에 한 번 실행. 반드시 static 메소드여야 한다.
@AfterAll 모든 테스트 메소드가 실행된 후에 한 번 실행. 반드시 static 메소드여야 한다.
@DisplayName 테스트 클래스나 테스트 메소드의 이름을 커스텀할 수 있다.
@Disabled 특정 테스트 클래스나 메소드를 비활성화한다.

 

 

조건부 애노테이션

애노테이션 설명
@EnabledOnOs 특정 운영체제에서만 테스트를 실행한다. @EnabledOnOs(OS.WINDOWS)
@DisabledOnOs 특정 운영체제에서 테스트를 비활성화한다. @DisabledOnOs(OS.MAC)
@EnabledOnJre 특정 JRE 버전에서만 테스트를 실행한다. @EnabledOnJre(JRE.JAVA_11)
@DisabledOnJre 특정 JRE 버전에서 테스트를 비활성화한다. @DisabledOnJre(JRE.JAVA_8)
@Enabledlf SpEL(Spring Expression Language) 표현식을 사용하여 조건이 참일 때만 테스트를 실행한다. @EnabledIf("2 * 3 == 6")
@Disabledlf SpEL(Spring Expression Language) 표현식을 사용하여 조건이 참일 때 비활성화한다. @DisabledIf("'CI' == systemEnvironment['ENV']")

 

 

테스트 메소드 순서 애노테이션

@TestMethodOrder

테스트 메소드 실행 순서를 지정할 수 있다. 클래스와 메소드에 적용할 수 있다.

@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class OrderedTests {
    @Test
    @Order(1)
    void testA() {
        // 테스트 코드
    }
    @Test
    @Order(2)
    void testB() {
        // 테스트 코드
    }
}

 

 

테스트 인스턴스 애노테이션

@TestInstance

테스트 클래스의 인스턴스 라이프사이클을 제어하는 데 사용된다. 이를 통해 테스트 인스턴스가 생성되고 파괴되는 시점을 결정할 수 있다. 기본적으로 JUnit 5는 각 테스트 메소드마다 새로운 인스턴스를 생성하지만, @TestInstance를 사용하면 클래스당 하나의 인스턴스를 사용할 수 있다.

옵션 설명
TestInstance.Lifecycle.PER_METHOD 기본값이다.
각 테스트 메소드마다 새로운 테스트 인스턴스가 생성된다.
@BeforeAll과 @AfterAll 메소드가 static이어야 합니다.
각 테스트가 독립적으로 실행되어야 하는 경우 유용합니다.
TestInstance.Lifecycle.PER_CLASS 클래스당 하나의 테스트 인스턴스가 생성된다.
@BeforeAll과 @AfterAll 메소드를 static으로 정의할 필요가 없다.
테스트 메소드들이 상태를 공유할 수 있다.
클래스 수준에서 상태를 유지해야 하는 경우 사용한다.
인스턴스 생성 비용이 높을 때 인스턴스 재사용으로 성능 최적화할 수 있다.
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class TestLifecycle {

    @BeforeAll
    void init() {
        // 클래스당 하나의 인스턴스 초기화 코드
        System.out.println("BeforeAll - 초기화 코드");
    }
    
    @Test
    void testA() {
        // 테스트 코드 A
        System.out.println("testA 실행");
    }

    @Test
    void testB() {
        // 테스트 코드 B
        System.out.println("testB 실행");
    }
}

 

 

파라미터화 테스트 애노테이션

@ParameterizedTest

하나의 테스트 메서드를 여러 입력 값에 대해 반복 실행할 수 있게 해준다. 이를 통해 중복 코드를 줄이고 다양한 입력 값에 대한 테스트를 효율적으로 수행할 수 있다. 동일한 로직을 다양한 입력 값에 대해 검증하고자 할 때 사용한다.

@ValueSource

매개 변수화된 테스트에서 사용할 단일 값 소스를 제공하는 어노테이션이다. 지원되는 타입은 short, byte, int, long, float, double, char, boolean, String 등이 있다. 매개 변수화된 테스트에 단순한 리터럴 값(숫자, 문자열 등)을 제공할 때 사용한다.

public class ValueSourceTests {

    @ParameterizedTest
    @ValueSource(ints = {1, 2, 3, 4, 5})
    void testWithValueSource(int argument) {
        assertNotNull(argument);
    }
}

@CsvSource

JUnit 5의 파라미터화된 테스트에서 사용되는 어노테이션 중 하나로, CSV(Comma-Separated Values) 형식의 데이터를 테스트 메서드에 제공할 수 있게 해준다. 이를 통해 복잡한 입력 값 세트를 간편하게 지정하고, 다양한 경우의 테스트를 효율적으로 수행할 수 있다. 원시 자료형만 가능하다.

public class CsvSourceTests {

    @ParameterizedTest
    @CsvSource({
        "1, 2, 3",
        "2, 3, 5",
        "3, 5, 8"
    })
    void testAddition(int a, int b, int expected) {
        assertEquals(expected, a + b);
    }

    @ParameterizedTest
    @CsvSource({
        "racecar, true",
        "radar, true",
        "hello, false"
    })
    void testIsPalindrome(String candidate, boolean expected) {
        assertEquals(expected, isPalindrome(candidate));
    }

    boolean isPalindrome(String text) {
        return new StringBuilder(text).reverse().toString().equals(text);
    }

    @ParameterizedTest
    @CsvSource(value = {
        "1; 2; 3",
        "2; 3; 5",
        "3; 5; 8"
    }, delimiter = ';')
    void testAdditionWithCustomDelimiter(int a, int b, int expected) {
        assertEquals(expected, a + b);
    }
}

@MethodSource

테스트 메서드에 제공할 매개 변수들을 외부 메서드에서 생성하여 제공할 수 있게 해준다. 이를 통해 복잡한 테스트 데이터를 동적으로 생성하거나 다양한 형식의 데이터를 사용할 수 있다.

public class MethodSourceTests {

    @ParameterizedTest
    @MethodSource("provideStringsForIsBlank")
    void testIsBlank(String input) {
        assertTrue(input == null || input.trim().isEmpty());
    }

    static Stream<String> provideStringsForIsBlank() {
        return Stream.of(null, "", "  ");
    }

    @ParameterizedTest
    @MethodSource("provideArgumentsForAddition")
    void testAddition(int a, int b, int expected) {
        assertEquals(expected, a + b);
    }

    static Stream<Arguments> provideArgumentsForAddition() {
        return Stream.of(
            Arguments.of(1, 2, 3),
            Arguments.of(2, 3, 5),
            Arguments.of(3, 5, 8)
        );
    }

    @ParameterizedTest
    @MethodSource("provideListForTesting")
    void testList(List<Integer> numbers, int expectedSum) {
        int sum = numbers.stream().mapToInt(Integer::intValue).sum();
        assertEquals(expectedSum, sum);
    }

    static Stream<Arguments> provideListForTesting() {
        return Stream.of(
            Arguments.of(Arrays.asList(1, 2, 3), 6),
            Arguments.of(Arrays.asList(4, 5, 6), 15),
            Arguments.of(Arrays.asList(7, 8, 9), 24)
        );
    }
}

 

@EnumSource

특정 열거형(enum) 타입의 모든 상수나 일부 상수를 테스트 메서드에 제공할 수 있게 해준다. 이를 통해 enum 타입의 다양한 경우를 테스트할 수 있다.

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;

import static org.junit.jupiter.api.Assertions.*;

public class EnumSourceTests {

    enum Color {
        RED, GREEN, BLUE, YELLOW
    }

    /**
     * 테스트: 모든 Color 열거형 값을 테스트한다.
     */
    @ParameterizedTest
    @EnumSource(Color.class)
    void testAllColors(Color color) {
        assertNotNull(color);
    }

    /**
     * 테스트: RED 및 BLUE만을 테스트한다.
     */
    @ParameterizedTest
    @EnumSource(value = Color.class, names = {"RED", "BLUE"})
    void testSpecificColors(Color color) {
        assertTrue(color == Color.RED || color == Color.BLUE);
    }

    /**
     * 테스트: GREEN을 제외한 모든 색을 테스트한다.
     */
    @ParameterizedTest
    @EnumSource(value = Color.class, names = "GREEN", mode = EnumSource.Mode.EXCLUDE)
    void testExcludeColors(Color color) {
        assertFalse(color == Color.GREEN);
    }

    /**
     * 테스트: 이름이 ".*LLOW"와 일치하는 색을 테스트한다 (예: YELLOW).
     */
    @ParameterizedTest
    @EnumSource(value = Color.class, names = ".*LLOW", mode = EnumSource.Mode.MATCH_ALL)
    void testRegexColors(Color color) {
        assertTrue(color == Color.YELLOW);
    }
}

 

 

Mockito 애노테이션

@Mock

목 객체를 생성한다. 목 객체는 실제 객체를 대신하여 테스트에 사용된다.

@ExtendWith(MockitoExtension.class)
public class MyTests {

    @Mock
    private MyService myService;

    @Test
    void testService() {
        when(myService.doSomething()).thenReturn("Mocked Result");
        assertEquals("Mocked Result", myService.doSomething());
    }
}

@InjectMocks

Mockito 라이브러리를 사용하여 모의 객체(mock)를 주입할 실제 객체를 생성한다. 이를 통해 의존성을 자동으로 주입받을 수 있다. 테스트 대상 객체를 생성하고, 해당 객체의 의존성을 목(mock)으로 주입하고자 할 때 사용한다.

@ExtendWith(MockitoExtension.class)
public class MyTests {

    @Mock
    private MyRepository myRepository;

    @InjectMocks
    private MyService myService;

    @Test
    void testService() {
        when(myRepository.find()).thenReturn("Mocked Data");
        assertEquals("Mocked Data", myService.getData());
    }
}

@Spy

실제 객체를 생성하되, 일부 메소드만 목킹한다. 실 객체의 동작을 유지하면서 특정 메소드의 동작을 변경할 때 사용한다.

@ExtendWith(MockitoExtension.class)
public class MyTests {

    @Spy
    private MyService myService;

    @Test
    void testService() {
        doReturn("Mocked Result").when(myService).doSomething();
        assertEquals("Mocked Result", myService.doSomething());
    }
}

@Captor

인자 캡처를 위한 목 캡처 객체를 생성한다. 목 객체의 메소드가 호출될 때 전달된 인자를 캡처하여 확인할 때 사용한다.

@ExtendWith(MockitoExtension.class)
public class MyTests {

    @Mock
    private MyService myService;

    @Captor
    private ArgumentCaptor<String> captor;

    @Test
    void testService() {
        myService.doSomething("Argument");
        verify(myService).doSomething(captor.capture());
        assertEquals("Argument", captor.getValue());
    }
}

@MockBean

스프링 컨텍스트에서 특정 빈을 목 객체로 대체하여, 통합 테스트 시 다른 빈이 목 객체를 사용하도록 한다.

@SpringBootTest
public class MyTests {

    @MockBean
    private MyService myService;

    @Test
    void testService() {
        when(myService.doSomething()).thenReturn("Mocked Result");
        assertEquals("Mocked Result", myService.doSomething());
    }
}

@SpyBean

 스프링 컨텍스트에서 특정 빈을 스파이 객체로 대체하여, 통합 테스트 시 다른 빈이 스파이 객체를 사용하도록 한다.

@SpringBootTest
public class MyTests {

    @SpyBean
    private MyService myService;

    @Test
    void testService() {
        doReturn("Mocked Result").when(myService).doSomething();
        assertEquals("Mocked Result", myService.doSomething());
    }
}

 

 

'JVM' 카테고리의 다른 글

MockServer  (0) 2024.07.29
BDDMockito  (0) 2024.07.28
테스트 커버리지와 JaCoCo  (0) 2024.07.27
StringBuffer vs StringBuilder  (0) 2024.07.22
java.security.invalidKeyException: Illegal Key Size  (0) 2024.05.04