728x90
- 본 프로젝트는 테스트 주도 개발(Test-driven development, TDD)로 만들어짐
- Repository 작성과 함께 테스트도 함께 작성함
- 실제 데이터베이스는 사용X(JPA), 메모리DB사용
Config
AppConfig
// 스프링 부트 실행시, 해당 값들을 먼저 참조 -> Config Class
@Configuration
class AppConfig {
/* val database = TodoDataBase()와 같은 형태로 static 걸어서 쓰지만
Spring의 패러다임은 자동으로 주입되게 만드는 것임.*/
@Bean(initMethod = "init") // Bean으로 등록, init지정, 빈이 만들어질때 어떤 메소드 참조할지 정한다
fun todoDataBase(): TodoDataBase {
return TodoDataBase()
}
}
DataBase
Todo
//Column
data class Todo(
var index: Int? = null, // 일정 index
var title: String? = null, // 일정 title
var description: String? = null, // 일정 설명
var schedule: LocalDateTime? = null, // 일정 시간
var createdAt: LocalDateTime? = null, // 생성 시간
var updatedAt: LocalDateTime? = null, // 업데이트 시간
)
TodoDataBase
//Index
data class TodoDataBase(
var index: Int = 0,
var todoList: MutableList<Todo> = mutableListOf()
) {
fun init() {
this.index = 0
this.todoList = mutableListOf() //초기화
println("[DEBUG] todo database init")
}
}
Repository
TodoRepository
interface TodoRepository {
fun save(todo: Todo): Todo?
fun saveAll(todoList: MutableList<Todo>): Boolean
fun delete(index: Int): Boolean
fun findOne(index: Int): Todo?
fun findAll(): MutableList<Todo>
}
TodoRepositoryImpl
// TodoRepository 상속
@Service
class TodoRepositoryImpl : TodoRepository {
@Autowired // database init(Config)가 자동으로 주입됨, Autowired로 언제든지 접근 가능
lateinit var todoDataBase: TodoDataBase
override fun save(todo: Todo): Todo? {
// 1. index?
return todo.index?.let { index ->
// update(값이 있을 때)
findOne(index)?.apply {
this.title = todo.title
this.description = todo.description
this.schedule = todo.schedule
this.updatedAt = LocalDateTime.now()
}
} ?: kotlin.run {
// insert(값이 없을 때)
todo.apply {
this.index = ++todoDataBase.index
this.createdAt = LocalDateTime.now()
this.updatedAt = LocalDateTime.now()
}.run {
todoDataBase.todoList.add(todo)
this // return
}
}
}
override fun saveAll(todoList: MutableList<Todo>): Boolean {
return try {
todoList.forEach {
save(it)
}
true
} catch (e: Exception) {
false
}
}
// override fun update(todo: Todo): Todo {
// // jpa
// // save db index -> 인덱스 있냐 업냐, 있으면 -> 업데이트, 없으면 -> insert
// }
override fun delete(index: Int): Boolean {
return findOne(index)?.let {
todoDataBase.todoList.remove(it)
true // 값이 있을 때
} ?: kotlin.run {
false // 값이 없을 때
}
}
override fun findOne(index: Int): Todo? {
return todoDataBase.todoList.first { it.index == index }
}
override fun findAll(): MutableList<Todo> {
return todoDataBase.todoList
}
}
Test
TodoRepository
//TDD : Test만들면서 최소한의 코드를 코딩해 나간다
@ExtendWith(SpringExtension::class)
@SpringBootTest(classes = [TodoRepositoryImpl::class, AppConfig::class]) // 특정 클래스만 테스트(import), 효율적 테스트 위해, Bean도 불러와 준다
class TodoRepositoryTest {
@Autowired
lateinit var todoRepositoryImpl: TodoRepositoryImpl
// Extension 기능 중 하나, 테스트가 실행되기 전에 무조건 실행됨
@BeforeEach
fun before() {
todoRepositoryImpl.todoDataBase.init()
}
@Test
fun saveTest() {
val todo = Todo().apply {
this.title = "테스트 일정"
this.description = "테스트"
this.schedule = LocalDateTime.now()
}
val result = todoRepositoryImpl.save(todo)
// 자동으로 생성해주는 데이터베이스 값 Test -> Pass
Assertions.assertEquals(1, result?.index)
Assertions.assertNotNull(result?.createdAt)
Assertions.assertNotNull(result?.updatedAt)
Assertions.assertEquals("테스트 일정", result?.title)
Assertions.assertEquals("테스트", result?.description)
}
@Test
fun saveAllTest() {
val todoList = mutableListOf(
Todo().apply {
this.title = "테스트 일정"
this.description = "테스트"
this.schedule = LocalDateTime.now()
},
Todo().apply {
this.title = "테스트 일정"
this.description = "테스트"
this.schedule = LocalDateTime.now()
},
Todo().apply {
this.title = "테스트 일정"
this.description = "테스트"
this.schedule = LocalDateTime.now()
}
)
val result = todoRepositoryImpl.saveAll(todoList)
Assertions.assertEquals(true, result)
}
@Test
fun findOneTest() {
println()
val todoList = mutableListOf(
Todo().apply {
this.title = "테스트 일정1"
this.description = "테스트"
this.schedule = LocalDateTime.now()
},
Todo().apply {
this.title = "테스트 일정2"
this.description = "테스트"
this.schedule = LocalDateTime.now()
},
Todo().apply {
this.title = "테스트 일정3"
this.description = "테스트"
this.schedule = LocalDateTime.now()
}
)
todoRepositoryImpl.saveAll(todoList)
val result = todoRepositoryImpl.findOne(2)
Assertions.assertNotNull(result)
Assertions.assertEquals("테스트 일정2", result?.title)
}
@Test
fun updateTest() {
val todo = Todo().apply {
this.title = "테스트 일정"
this.description = "테스트"
this.schedule = LocalDateTime.now()
}
val insertTodo = todoRepositoryImpl.save(todo)
val newTodo = Todo().apply {
this.index = insertTodo?.index
this.title = "업데이트 일정"
this.description = "업데이트 테스트"
this.schedule = LocalDateTime.now()
}
val result = todoRepositoryImpl.save(newTodo)
Assertions.assertNotNull(result)
Assertions.assertEquals(insertTodo?.index, result?.index)
Assertions.assertEquals("업데이트 일정", result?.title)
Assertions.assertEquals("업데이트 테스트", result?.description)
}
}
728x90
'ETC.. > Spring' 카테고리의 다른 글
[Spring] Spring Boot로 ToDoApp만들기(투두 앱) (3) (0) | 2021.04.11 |
---|---|
[Spring] Spring Boot로 ToDoApp만들기(투두 앱) (2) (0) | 2021.04.07 |
[Spring] Spring Boot Junit 단위 테스트 설명 & 예제 (Kotlin) (0) | 2021.04.04 |
[Spring] Spring Boot 예외 처리 설명 & 예제 (Kotlin) (0) | 2021.03.17 |
[Spring] SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet (0) | 2021.03.16 |