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

JSON 출력기 만들기 #98

Merged
merged 4 commits into from
Aug 20, 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
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
public enum ExportFileType {
CSV,
TSV,
// JSON, // TODO: 강의 시간 상 구현을 생략함. 구현하면 TODO 삭제
JSON,
// SQL_INSERT, // TODO: 강의 시간 상 구현을 생략함. 구현하면 TODO 삭제
;
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public static List<MockDataTypeObject> toObjects() {
}

public boolean isBaseType() { return baseType == null; }
public MockDataType jsonType() { return isBaseType() ? this : baseType; }

public MockDataTypeObject toObject() {
return new MockDataTypeObject(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package uno.fastcampus.testdata.service.exporter;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import uno.fastcampus.testdata.domain.constant.ExportFileType;
import uno.fastcampus.testdata.dto.SchemaFieldDto;
import uno.fastcampus.testdata.dto.TableSchemaDto;
import uno.fastcampus.testdata.service.generator.MockDataGeneratorContext;

import java.util.*;
import java.util.stream.IntStream;

@Slf4j
@RequiredArgsConstructor
@Component
public class JsonFileExporter implements MockDataFileExporter {

private final MockDataGeneratorContext mockDataGeneratorContext;
private final ObjectMapper mapper;

@Override
public ExportFileType getType() {
return ExportFileType.JSON;
}

@Override
public String export(TableSchemaDto dto, Integer rowCount) {
try {
List<Map<String, Object>> list = new ArrayList<>();

IntStream.range(0, rowCount).forEach(i -> {
Map<String, Object> map = new LinkedHashMap<>();
dto.schemaFields().stream()
.sorted(Comparator.comparing(SchemaFieldDto::fieldOrder))
.forEach(field -> {
String generatedValue = mockDataGeneratorContext.generate(
field.mockDataType(),
field.blankPercent(),
field.typeOptionJson(),
field.forceValue()
);
if (generatedValue == null) {
map.put(field.fieldName(), null);
} else {
var jsonValue = switch (field.mockDataType().jsonType()) {
case NUMBER -> Long.valueOf(generatedValue);
case BOOLEAN -> Boolean.valueOf(generatedValue);
default -> generatedValue;
};
map.put(field.fieldName(), jsonValue);
}
});
list.add(map);
});

return mapper.writeValueAsString(list);
} catch (JsonProcessingException e) {
log.warn("테이블 스키마 데이터를 JSON으로 변환하는데 실패했습니다 - {}", dto, e);
return "";
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;

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

Expand Down Expand Up @@ -34,4 +36,35 @@ void givenMockDataType_whenReading_thenReturnsEnumElementObject() {
assertThat(result.toString()).contains("name", "requiredOptions", "baseType");
}

@CsvSource(textBlock = """
STRING, STRING
NUMBER, NUMBER
BOOLEAN, BOOLEAN
DATETIME, DATETIME
ENUM, ENUM

SENTENCE, STRING
PARAGRAPH, STRING
UUID, STRING
EMAIL, STRING
CAR, STRING
ROW_NUMBER, NUMBER
NAME, STRING
"""
)
@DisplayName("자료형이 주어지면, JSON에 호환되는 자료형을 반환한다.")
@ParameterizedTest(name = "{index}. {0} => Json Type \"{1}\"")
void givenMockDataType_whenReading_thenReturnsJsonCompatibleMockDataType(
MockDataType input,
MockDataType expected
) {
// Given

// When
MockDataType actual = input.jsonType();

// Then
assertThat(actual).isEqualTo(expected);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package uno.fastcampus.testdata.service.exporter;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Spy;
import org.mockito.junit.jupiter.MockitoExtension;
import uno.fastcampus.testdata.domain.constant.ExportFileType;
import uno.fastcampus.testdata.domain.constant.MockDataType;
import uno.fastcampus.testdata.dto.SchemaFieldDto;
import uno.fastcampus.testdata.dto.TableSchemaDto;
import uno.fastcampus.testdata.service.generator.MockDataGeneratorContext;

import java.util.Set;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.*;
import static org.mockito.Mockito.times;

@DisplayName("[Logic] Json 파일 출력기 테스트")
@ExtendWith(MockitoExtension.class)
class JsonFileExporterTest {

@InjectMocks private JsonFileExporter sut;

@Mock private MockDataGeneratorContext mockDataGeneratorContext;
@Spy private ObjectMapper mapper;

@DisplayName("이 파일 출력기의 유형은 JSON이다.")
@Test
void givenNothing_whenCheckingType_thenReturnsJsonType() {
// Given

// When & Then
assertThat(sut.getType()).isEqualTo(ExportFileType.JSON);
}

@DisplayName("테이블 스키마 정보와 행 수가 주어지면, JSON 형식의 문자열을 생성한다.")
@Test
void givenSchemaAndRowCount_whenExporting_thenReturnsJsonFormattedString() throws Exception {
// Given
TableSchemaDto dto = TableSchemaDto.of(
"test_schema",
"uno",
null,
Set.of(
SchemaFieldDto.of("id", MockDataType.ROW_NUMBER, 1, 0, null, null),
SchemaFieldDto.of("name", MockDataType.NAME, 2, 0, null, null),
SchemaFieldDto.of("created_at", MockDataType.DATETIME, 5, 0, null, null),
SchemaFieldDto.of("age", MockDataType.NUMBER, 3, 0, null, null),
SchemaFieldDto.of("car", MockDataType.CAR, 4, 0, null, null)
)
);
int rowCount = 10;
given(mockDataGeneratorContext.generate(eq(MockDataType.ROW_NUMBER), any(), any(), any())).willReturn("1");
given(mockDataGeneratorContext.generate(eq(MockDataType.NAME), any(), any(), any())).willReturn("test-name");
given(mockDataGeneratorContext.generate(eq(MockDataType.DATETIME), any(), any(), any())).willReturn("2024-01-02T03:04:05");
given(mockDataGeneratorContext.generate(eq(MockDataType.NUMBER), any(), any(), any())).willReturn(null);
given(mockDataGeneratorContext.generate(eq(MockDataType.CAR), any(), any(), any())).willReturn("test-횬다이");

// When
String result = sut.export(dto, rowCount);

// Then
System.out.println(result); // 관찰용
djkeh marked this conversation as resolved.
Show resolved Hide resolved
assertThat(result)
.startsWith("[")
.endsWith("]")
.contains("""
{"id":1,"name":"test-name","age":null,"car":"test-횬다이","created_at":"2024-01-02T03:04:05"}"""
);
then(mockDataGeneratorContext).should(times(rowCount * dto.schemaFields().size())).generate(any(), any(), any(), any());
then(mapper).should().writeValueAsString(any());
}

@DisplayName("JSON 변환에 실패하면, 빈 문자열을 반환한다.")
@Test
void givenSchemaAndRowCount_whenFailingToJsonFormatting_thenReturnsEmptyString() throws Exception {
// Given
TableSchemaDto dto = TableSchemaDto.of("test_schema", "uno", null, Set.of(SchemaFieldDto.of("name", MockDataType.NAME, 1, 0, null, null)));
int rowCount = 10;
given(mockDataGeneratorContext.generate(any(), any(), any(), any())).willReturn("test-value");
willThrow(JsonProcessingException.class).given(mapper).writeValueAsString(any());

// When
String result = sut.export(dto, rowCount);

// Then
assertThat(result).isEqualTo("");
then(mockDataGeneratorContext).should(times(rowCount * dto.schemaFields().size())).generate(any(), any(), any(), any());
then(mapper).should().writeValueAsString(any());
}

}
Loading