Spring boot에서 unit & integration 테스트하기
Java Test Unit
자바에서 대표적인 테스트 프레임워크는 JUnit이다.
결과를 확인하기 위한 matcher를 지워하는 Hamcrest 프레임워크도 있다.
아래는 다양한 사용방법이다.
public class AssertTests {
@Test
public void testAssertEquals() {
assertEquals("failure - strings are not equal", "text", "text");
}
@Test
public void testAssertFalse() {
assertFalse("failure - should be false", false);
}
@Test
public void testAssertNotNull() {
assertNotNull("should not be null", new Object());
}
@Test
public void testAssertNotSame() {
assertNotSame("should not be same Object", new Object(), new Object());
}
@Test
public void testAssertNull() {
assertNull("should be null", null);
}
@Test
public void testAssertSame() {
Integer aNumber = Integer.valueOf(768);
assertSame("should be same", aNumber, aNumber);
}
// JUnit Matchers assertThat
@Test
public void testAssertThatBothContainsString() {
assertThat("albumen", both(containsString("a")).and(containsString("b")));
}
@Test
public void testAssertThatHasItems() {
assertThat(Arrays.asList("one", "two", "three"), hasItems("one", "three"));
}
@Test
public void testAssertThatEveryItemContainsString() {
assertThat(Arrays.asList(new String[] { "fun", "ban", "net" }), everyItem(containsString("n")));
}
// Core Hamcrest Matchers with assertThat
@Test
public void testAssertThatHamcrestCoreMatchers() {
assertThat("good", allOf(equalTo("good"), startsWith("good")));
assertThat("good", not(allOf(equalTo("bad"), equalTo("good"))));
assertThat("good", anyOf(equalTo("bad"), equalTo("good")));
assertThat(7, not(CombinableMatcher.<Integer> either(equalTo(3)).or(equalTo(4))));
assertThat(new Object(), not(sameInstance(new Object())));
}
}
Spring Boot Application unit test 하기
Spring boot는 @SpringBootTest라는 어노테이션을 제공해준다.
- 포트를 지정하여 다른 웹 환경에서 테스트를 할 수 있도록 지원해준다.
- property 들을 커스터마이징 할 수 있도록 해준다.
- 웹 테스트를 위한 TestRestTemplate, WebTestClient 빈을 등록해준다.
Service 테스트 하기
서비스를 테스트하기 위해서는 외부 component로부터 고립도록 해야 한다. 아래 코드에서는 remote API를 호출하는RestTemplate를 고립화해야한다. <p
@RunWith(SpringRunner.class)
@SpringBootTest
public class MangaServiceUnitTest {
@Autowired
private MangaService mangaService;
// MockBean is the annotation provided by Spring that wraps mockito one
// Annotation that can be used to add mocks to a Spring ApplicationContext.
// If any existing single bean of the same type defined in the context will be replaced by the mock, if no existing bean is defined a new one will be added.
@MockBean
private RestTemplate template;
@Test
public void testGetMangasByTitle() throws IOException {
// Parsing mock file
MangaResult mRs = JsonUtils.jsonFile2Object("ken.json", MangaResult.class);
// Mocking remote service
when(template.getForEntity(any(String.class), any(Class.class))).thenReturn(new ResponseEntity(mRs, HttpStatus.OK));
// I search for goku but system will use mocked response containing only ken, so I can check that mock is used.
List<Manga> mangasByTitle = mangaService.getMangasByTitle("goku");
assertThat(mangasByTitle).isNotNull()
.isNotEmpty()
.allMatch(p -> p.getTitle()
.toLowerCase()
.contains("ken"));
}
}