Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: meilisearch testcontainer 추가 #61

Merged
merged 1 commit into from
May 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 2 additions & 36 deletions api/src/main/java/vook/server/api/devhelper/InitService.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;

@Service
Expand All @@ -35,6 +34,7 @@ public class InitService {
private final UserRepository userRepository;
private final TermsRepository termsRepository;
private final DemoTermSearchService searchService;
private final TestTermsLoader testTermsLoader;

public void init() {
deleteAll();
Expand All @@ -43,7 +43,7 @@ public void init() {
termsRepository.save(Terms.of("개인정보 수집 이용 약관", loadContents("classpath:init/개인정보_수집_이용_약관.txt"), true));
termsRepository.save(Terms.of("마케팅 메일 수신 약관", loadContents("classpath:init/마케팅_메일_수신_약관.txt"), false));

List<DemoTerm> devTerms = getTerms("classpath:init/개발.tsv");
List<DemoTerm> devTerms = testTermsLoader.getTerms("classpath:init/개발.tsv");
demoTermRepository.saveAll(devTerms);

searchService.init();
Expand Down Expand Up @@ -76,38 +76,4 @@ private String loadContents(String location) {
throw new RuntimeException(e);
}
}

private List<DemoTerm> getTerms(String location) {
try {
// file로 바로 접근 할 경우, IDE에서는 접근 가능하나, jar로 패키징 후 실행 시에는 접근 불가능
// ref) https://velog.io/@haron/트러블슈팅-Spring-IDE-에서-되는데-배포하면-안-돼요
InputStream tsvFileInputStream = resourceLoader.getResource(location).getInputStream();
CsvReader tsvReader = new CsvReader("\t");
List<RawTerm> rawTerms = tsvReader.readValue(tsvFileInputStream, RawTerm.class);
return toTerms(rawTerms);
} catch (IOException e) {
throw new RuntimeException(e);
}
}

private static List<DemoTerm> toTerms(List<RawTerm> rawTerms) {
return rawTerms.stream()
.map(RawTerm::toTerm)
.toList();
}

public static class RawTerm {
private String term;
private String synonyms;
private String meaning;

public DemoTerm toTerm() {
DemoTerm term = DemoTerm.forCreateOf(this.term, this.meaning);
String[] synonymArray = this.synonyms.split("//n");
Arrays.stream(synonymArray)
.map(String::trim)
.forEach(term::addSynonym);
return term;
}
}
}
52 changes: 52 additions & 0 deletions api/src/main/java/vook/server/api/devhelper/TestTermsLoader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package vook.server.api.devhelper;

import lombok.RequiredArgsConstructor;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Component;
import vook.server.api.model.demo.DemoTerm;

import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;

@Component
@RequiredArgsConstructor
public class TestTermsLoader {

private final ResourceLoader resourceLoader;

public List<DemoTerm> getTerms(String location) {
try {
// file로 바로 접근 할 경우, IDE에서는 접근 가능하나, jar로 패키징 후 실행 시에는 접근 불가능
// ref) https://velog.io/@haron/트러블슈팅-Spring-IDE-에서-되는데-배포하면-안-돼요
InputStream tsvFileInputStream = resourceLoader.getResource(location).getInputStream();
CsvReader tsvReader = new CsvReader("\t");
List<RawTerm> rawTerms = tsvReader.readValue(tsvFileInputStream, RawTerm.class);
return toTerms(rawTerms);
} catch (IOException e) {
throw new RuntimeException(e);
}
}

static List<DemoTerm> toTerms(List<RawTerm> rawTerms) {
return rawTerms.stream()
.map(RawTerm::toTerm)
.toList();
}

static class RawTerm {
private String term;
private String synonyms;
private String meaning;

public DemoTerm toTerm() {
DemoTerm term = DemoTerm.forCreateOf(this.term, this.meaning);
String[] synonymArray = this.synonyms.split("//n");
Arrays.stream(synonymArray)
.map(String::trim)
.forEach(term::addSynonym);
return term;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import com.meilisearch.sdk.model.TypoTolerance;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import vook.server.api.model.demo.DemoTerm;
import vook.server.api.model.demo.DemoTermSynonym;
Expand All @@ -19,13 +18,17 @@
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class DemoTermSearchService extends MeilisearchService {

private static final String DEMO_TERMS_INDEX_UID = "demo-terms";

private final ObjectMapper objectMapper;

public DemoTermSearchService(MeilisearchProperties properties, ObjectMapper objectMapper) {
super(properties);
this.objectMapper = objectMapper;
}

public void clearAll() {
clearAll(DEMO_TERMS_INDEX_UID);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package vook.server.api.outbound.search;

import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Setter
@Getter
@Component
@ConfigurationProperties(prefix = "service.meilisearch")
public class MeilisearchProperties {
private String host;
private String apiKey;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,15 @@
import com.meilisearch.sdk.Index;
import com.meilisearch.sdk.model.IndexesQuery;
import com.meilisearch.sdk.model.Results;
import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Value;

import java.util.Arrays;

public abstract class MeilisearchService {

@Value("${service.meilisearch.host:}")
protected String host;
protected final Client client;

@Value("${service.meilisearch.apiKey:}")
protected String apiKey;

protected Client client;

@PostConstruct
public void postConstruct() {
this.client = new Client(new Config(host, apiKey));
protected MeilisearchService(MeilisearchProperties properties) {
this.client = new Client(new Config(properties.getHost(), properties.getApiKey()));
}

protected void clearAll(String uidPrefix) {
Expand Down
20 changes: 19 additions & 1 deletion api/src/test/java/vook/server/api/testhelper/ApiTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.testcontainers.containers.MariaDBContainer;
import vook.server.api.outbound.search.MeilisearchProperties;

import java.util.Map;
import java.util.TimeZone;
Expand All @@ -19,19 +22,34 @@ public abstract class ApiTest {
protected TestRestTemplate rest;

@ServiceConnection
protected static final MariaDBContainer mariaDBContainer = new MariaDBContainer<>("mariadb:10.11")
protected static final MariaDBContainer<?> mariaDBContainer = new MariaDBContainer<>("mariadb:10.11")
.withDatabaseName("example")
.withUsername("user")
.withPassword("userPw")
.withConfigurationOverride("db/conf")
.withTmpFs(Map.of("/var/lib/mysql", "rw"));

protected static final MeilisearchContainer meilisearchContainer = new MeilisearchContainer("getmeili/meilisearch:v1.8.0");

static {
mariaDBContainer.start();
meilisearchContainer.start();
}

@BeforeEach
void init() {
TimeZone.setDefault(TimeZone.getTimeZone(DEFAULT_TIME_ZONE));
}

@Configuration
public static class TestConfig {

@Bean
public MeilisearchProperties meilisearchProperties() {
MeilisearchProperties meilisearchProperties = new MeilisearchProperties();
meilisearchProperties.setHost(meilisearchContainer.getHostUrl());
meilisearchProperties.setApiKey(meilisearchContainer.getMasterKey());
return meilisearchProperties;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package vook.server.api.testhelper;

import org.testcontainers.containers.GenericContainer;
import org.testcontainers.utility.DockerImageName;

public class MeilisearchContainer extends GenericContainer<MeilisearchContainer> {

private static final String DEFAULT_IMAGE_NAME = "getmeili/meilisearch:latest";

public MeilisearchContainer() {
this(DEFAULT_IMAGE_NAME);
}

public MeilisearchContainer(String dockerImageName) {
this(DockerImageName.parse(dockerImageName));
}

public MeilisearchContainer(DockerImageName dockerImageName) {
super(dockerImageName);
this.addExposedPort(7700);
this.addEnv("MEILI_MASTER_KEY", "aMasterKey");
}

public String getMasterKey() {
return this.getEnvMap().get("MEILI_MASTER_KEY");
}

/**
* Meilisearch에 접속하기 위한 URL을 반환한다.
*/
public String getHostUrl() {
return "http://" + getHost() + ":" + getMappedPort(7700);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package vook.server.api.web.routes.demo;

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import vook.server.api.app.demo.repo.DemoTermRepository;
import vook.server.api.devhelper.TestTermsLoader;
import vook.server.api.model.demo.DemoTerm;
import vook.server.api.outbound.search.DemoTermSearchService;
import vook.server.api.testhelper.ApiTest;
import vook.server.api.web.routes.demo.reqres.SearchTermRequest;
import vook.server.api.web.routes.demo.reqres.SearchTermResponse;

import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;

@Transactional
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class DemoWebServiceTest extends ApiTest {

@Autowired
private DemoWebService demoWebService;

@Autowired
private TestTermsLoader testTermsLoader;
@Autowired
private DemoTermRepository demoTermRepository;
@Autowired
private DemoTermSearchService demoTermSearchService;

@BeforeAll
void beforeAll() {
List<DemoTerm> terms = testTermsLoader.getTerms("classpath:init/개발.tsv");
demoTermRepository.saveAll(terms);
demoTermSearchService.init();
demoTermSearchService.addTerms(terms);
}

@AfterAll
void afterAll() {
demoTermSearchService.clearAll();
}

@Test
void searchTerm() {
SearchTermRequest searchTermRequest = new SearchTermRequest();
searchTermRequest.setQuery("하이브리드앱");
searchTermRequest.setWithFormat(false);
searchTermRequest.setHighlightPreTag("<em>");
searchTermRequest.setHighlightPostTag("</em>");

SearchTermResponse searchTermResponse = demoWebService.searchTerm(searchTermRequest);

assertThat(searchTermResponse).isNotNull();
assertThat(searchTermResponse.getQuery()).isEqualTo("하이브리드앱");
assertThat(searchTermResponse.getHits()).isNotEmpty();
}
}
3 changes: 0 additions & 3 deletions api/src/test/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,6 @@ logging:
orm:
jdbc: TRACE
service:
meilisearch:
host: http://localhost:7700
apiKey: aSampleMasterKey
jwt:
secret: vmfhaltmskdlstkfkdgodyroqkfwkdba
oauth2:
Expand Down
Loading