0. 개요
Spring Boot Test에서 엘라스틱서치 테스트 컨테이너를 띄워 테스트 해 보겠습니다.
nori도 사용할 것입니다.
1. 테스트
우선 테스트 엘라스틱 컨테이너를 띄워야 합니다.
이를 위해 의존성을 주입 받겠습니다.
// build.gradle
testImplementation("org.testcontainers:junit-jupiter:1.16.3")
테스트 파일 위치에 아래와 같이 만들겠습니다.
자세한 설명은 주석으로 달겠습니다.
@TestConfiguration
@EnableElasticsearchRepositories(basePackageClasses = UserSearchRepository.class)
public class ElasticTest extends AbstractElasticsearchConfiguration {
// nori를 다운받기 위해서 DockerImageName을 사용하지 않고 그보더 더 추상화된 GenericContainer를 사용했습니다.
private static final GenericContainer container;
static{
container = new GenericContainer(
new ImageFromDockerfile().withDockerfileFromBuilder(
b -> {
b.from("docker.elastic.co/elasticsearch/elasticsearch:7.10.2") // 엘라스틱 이미지입니다.
.run("bin/elasticsearch-plugin install analysis-nori") // 이미지에 nori를 다운 받습니다.
.build();
})
).withExposedPorts(9200, 9300)
.withFileSystemBind(
"es/settings/stop/english.txt",
"/usr/share/elasticsearch/config/settings/stop/english.txt", // 불용어 파일을 추가합니다.
BindMode.READ_ONLY)
.withFileSystemBind(
"es/settings/synonym/english.txt",
"/usr/share/elasticsearch/config/settings/synonym/english.txt", // 동의어 파일을 추가합니다.
BindMode.READ_ONLY)
.withEnv("discovery.type","single-node");
container.start();
}
//엘라스틱서치를 사용하기 위해서는 high와 low level을 사용하는데, 주로 high level을 사용합니다.
@Override
public RestHighLevelClient elasticsearchClient() {
String hostAddress = new StringBuilder()
.append(container.getHost())
.append(":")
.append(container.getMappedPort(9200))
.toString();
ClientConfiguration configuration = ClientConfiguration.builder()
.connectedTo(hostAddress)
.build();
return RestClients.create(configuration).rest();
}
}
컨테이너를 가져와서 사용할 테스트 파일을 만듭니다.
@Import(ElasticTest.class)
@SpringBootTest(classes = UserSearchRepository.class)
public class ESRepositoryTest {
@Autowired
UserSearchRepository repository;
@Test
void test() {
// given
RequestUserSaveDto info = RequestUserSaveDto
.builder()
.id(1L)
.name("ksb")
.age(20L)
.korean("하이 케이 에스 비")
.english("hello ksb")
.build();
UserDocument user = UserDocument.of(info);
// when
repository.save(user);
//then
UserDocument result = repository.findByName("ksb").get(0);
assertThat(result.getId()).isEqualTo(user.getId());
assertThat(result.getAge()).isEqualTo(user.getAge());
assertThat(result.getKorean()).isEqualTo(user.getKorean());
assertThat(result.getEnglish()).isEqualTo(user.getEnglish());
}
}
이제 필요 클래스를 하나씩 만듭니다.
우선 dto 먼저 만듭니다.
@AllArgsConstructor
@Getter
@Builder
public class RequestUserSaveDto {
private final Long id;
private final String name;
private final Long age;
private final String korean;
private final String english;
}
domain을 만듭니다.
@Document(indexName = "user_index")
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Builder
@Getter
@Setting(settingPath = "elastic/es-setting.json")
@Mapping(mappingPath = "elastic/es-mapping.json")
public class UserDocument {
private Long id;
private String name;
private Long age;
private String korean;
private String english;
@Field(type = FieldType.Date, format = DateFormat.custom, pattern = "uuuu-MM-dd'T'HH:mm:ss")
private LocalDateTime created;
public static UserDocument of(RequestUserSaveDto dto) {
return UserDocument.builder()
.id(dto.getId())
.name(dto.getName())
.age(dto.getAge())
.korean(dto.getKorean())
.english(dto.getEnglish())
.created(LocalDateTime.now())
.build();
}
}
repository를 만듭니다.
public interface UserSearchRepository extends ElasticsearchRepository<UserDocument, Long> {
List<UserDocument> findByName(String name);
}
끝.
이 글은 제가 만든 프로젝트의 일부분을 가져와서 작성했습니다.
자세한 파일 위치나 내용을 원하시면 아래 링크로 확인하시면 됩니다.
https://github.com/kang-seongbeom/ES-SpringBoot
이 테스트를 작성하기 까지 몇 가지 에러를 만날수 있었는데,
해당 트러블 슈팅은 아래 링크를 통해 남겨두겠습니다.
https://ksb-dev.tistory.com/315
https://ksb-dev.tistory.com/316
'엘라스틱 서치' 카테고리의 다른 글
스프링부트로 엘라스틱서치 쿼리 날리기 (0) | 2023.06.09 |
---|---|
ELK, Mysql, Kafka 구축 및 연동 (0) | 2023.06.02 |
엘라스틱서치 검색 Query DSL (0) | 2023.05.18 |
엘라스틱서치 데이터 삽입, 조회, 수정, 삭제, _bulk API (0) | 2023.05.03 |
엘라스틱서치 8.X 도커로 무작성 실행해보기 (0) | 2023.04.25 |