-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
* test: BrowseProblemsUseCase 단위 테스트 추가 * test: CheckProblemUseCase 단위 테스트 추가 * test: ReadProblemUseCase 단위 테스트 추가 * test: SubscribeWorkbookUseCase 단위 테스트 추가 * test: 이미 구독중인 경우에 대한 단위 테스트 추가 * test: kotest를 활용한 단위테스트로 변경 * test: ReadArticleUseCase 단위 테스트 추가 * test: ReadWorkbookUseCase 단위 테스트 추가 * refactor: unit test code
- Loading branch information
Showing
6 changed files
with
448 additions
and
0 deletions.
There are no files selected for viewing
75 changes: 75 additions & 0 deletions
75
api/src/test/kotlin/com/few/api/domain/article/usecase/ReadArticleUseCaseTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
package com.few.api.domain.article.usecase | ||
|
||
import com.few.api.domain.article.service.BrowseArticleProblemsService | ||
import com.few.api.domain.article.service.ReadArticleWriterRecordService | ||
import com.few.api.domain.article.service.dto.BrowseArticleProblemsOutDto | ||
import com.few.api.domain.article.service.dto.ReadWriterOutDto | ||
import com.few.api.domain.article.usecase.dto.ReadArticleUseCaseIn | ||
import com.few.api.repo.dao.article.ArticleDao | ||
import com.few.api.repo.dao.article.record.SelectArticleRecord | ||
import io.kotest.assertions.throwables.shouldThrow | ||
import io.kotest.core.spec.style.BehaviorSpec | ||
import io.mockk.every | ||
import io.mockk.mockk | ||
import io.mockk.verify | ||
|
||
import java.net.URL | ||
import java.time.LocalDateTime | ||
|
||
class ReadArticleUseCaseTest : BehaviorSpec({ | ||
|
||
lateinit var articleDao: ArticleDao | ||
lateinit var readArticleWriterRecordService: ReadArticleWriterRecordService | ||
lateinit var browseArticleProblemsService: BrowseArticleProblemsService | ||
lateinit var useCase: ReadArticleUseCase | ||
val useCaseIn = ReadArticleUseCaseIn(articleId = 1L) | ||
|
||
beforeContainer { | ||
articleDao = mockk<ArticleDao>() | ||
readArticleWriterRecordService = mockk<ReadArticleWriterRecordService>() | ||
browseArticleProblemsService = mockk<BrowseArticleProblemsService>() | ||
useCase = ReadArticleUseCase(articleDao, readArticleWriterRecordService, browseArticleProblemsService) | ||
} | ||
|
||
given("아티클 조회 요청이 온 상황에서") { | ||
`when`("아티클과 작가가 존재할 경우") { | ||
val record = SelectArticleRecord( | ||
articleId = 1L, | ||
writerId = 1L, | ||
mainImageURL = URL("https://jh-labs.tistory.com/"), | ||
title = "title", | ||
category = (10).toByte(), | ||
content = "content", | ||
createdAt = LocalDateTime.now() | ||
) | ||
val writerSvcOutDto = ReadWriterOutDto( | ||
writerId = 1L, | ||
name = "hunca", | ||
url = URL("https://jh-labs.tistory.com/") | ||
) | ||
val probSvcOutDto = BrowseArticleProblemsOutDto(problemIds = listOf(1, 2, 3)) | ||
|
||
every { articleDao.selectArticleRecord(any()) } returns record | ||
every { readArticleWriterRecordService.execute(any()) } returns writerSvcOutDto | ||
every { browseArticleProblemsService.execute(any()) } returns probSvcOutDto | ||
|
||
then("아티클이 정상 조회된다") { | ||
useCase.execute(useCaseIn) | ||
|
||
verify(exactly = 1) { articleDao.selectArticleRecord(any()) } | ||
verify(exactly = 1) { readArticleWriterRecordService.execute(any()) } | ||
verify(exactly = 1) { browseArticleProblemsService.execute(any()) } | ||
} | ||
} | ||
|
||
`when`("존재하지 않는 아티클일 경우") { | ||
every { articleDao.selectArticleRecord(any()) } returns null | ||
|
||
then("예외가 발생한다") { | ||
shouldThrow<Exception> { useCase.execute(useCaseIn) } | ||
|
||
verify(exactly = 1) { articleDao.selectArticleRecord(any()) } | ||
} | ||
} | ||
} | ||
}) |
45 changes: 45 additions & 0 deletions
45
api/src/test/kotlin/com/few/api/domain/problem/usecase/BrowseProblemsUseCaseTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package com.few.api.domain.problem.usecase | ||
|
||
import com.few.api.domain.problem.usecase.dto.BrowseProblemsUseCaseIn | ||
import com.few.api.repo.dao.problem.ProblemDao | ||
import com.few.api.repo.dao.problem.record.ProblemIdsRecord | ||
import io.kotest.assertions.throwables.shouldThrow | ||
import io.kotest.core.spec.style.BehaviorSpec | ||
import io.mockk.every | ||
import io.mockk.mockk | ||
import io.mockk.verify | ||
|
||
class BrowseProblemsUseCaseTest : BehaviorSpec({ | ||
|
||
lateinit var problemDao: ProblemDao | ||
lateinit var useCase: BrowseProblemsUseCase | ||
val useCaseIn = BrowseProblemsUseCaseIn(articleId = 1L) | ||
|
||
beforeContainer { | ||
problemDao = mockk<ProblemDao>() | ||
useCase = BrowseProblemsUseCase(problemDao) | ||
} | ||
|
||
given("특정 아티클에 대한") { | ||
`when`("문제가 존재할 경우") { | ||
val problemIdsRecord = ProblemIdsRecord(listOf(1, 2, 3)) | ||
every { problemDao.selectProblemsByArticleId(any()) } returns problemIdsRecord | ||
|
||
then("문제번호가 정상적으로 조회된다") { | ||
useCase.execute(useCaseIn) | ||
|
||
verify(exactly = 1) { problemDao.selectProblemsByArticleId(any()) } | ||
} | ||
} | ||
|
||
`when`("문제가 존재하지 않을 경우") { | ||
every { problemDao.selectProblemsByArticleId(any()) } returns null | ||
|
||
then("예외가 발생한다") { | ||
shouldThrow<Exception> { useCase.execute(useCaseIn) } | ||
|
||
verify(exactly = 1) { problemDao.selectProblemsByArticleId(any()) } | ||
} | ||
} | ||
} | ||
}) |
74 changes: 74 additions & 0 deletions
74
api/src/test/kotlin/com/few/api/domain/problem/usecase/CheckProblemUseCaseTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
package com.few.api.domain.problem.usecase | ||
|
||
import com.few.api.domain.problem.usecase.dto.CheckProblemUseCaseIn | ||
import com.few.api.repo.dao.problem.ProblemDao | ||
import com.few.api.repo.dao.problem.SubmitHistoryDao | ||
import com.few.api.repo.dao.problem.record.SelectProblemAnswerRecord | ||
import io.kotest.assertions.throwables.shouldThrow | ||
import io.kotest.core.spec.style.BehaviorSpec | ||
import io.kotest.matchers.shouldBe | ||
import io.mockk.every | ||
import io.mockk.mockk | ||
import io.mockk.verify | ||
|
||
class CheckProblemUseCaseTest : BehaviorSpec({ | ||
|
||
lateinit var problemDao: ProblemDao | ||
lateinit var submitHistoryDao: SubmitHistoryDao | ||
lateinit var useCase: CheckProblemUseCase | ||
|
||
beforeContainer { | ||
problemDao = mockk<ProblemDao>() | ||
submitHistoryDao = mockk<SubmitHistoryDao>() | ||
useCase = CheckProblemUseCase(problemDao, submitHistoryDao) | ||
} | ||
|
||
given("문제 정답 확인 요청이 온 상황에서") { | ||
`when`("제출 값과 문제 정답이 같을 경우") { | ||
val submissionVal = "1" | ||
val answer = submissionVal | ||
val useCaseIn = CheckProblemUseCaseIn(problemId = 1L, sub = submissionVal) | ||
val answerRecord = SelectProblemAnswerRecord(id = 1L, answer = answer, explanation = "해설입니다.") | ||
|
||
every { problemDao.selectProblemAnswer(any()) } returns answerRecord | ||
every { submitHistoryDao.insertSubmitHistory(any()) } returns 1L | ||
|
||
then("문제가 정답처리 된다") { | ||
val useCaseOut = useCase.execute(useCaseIn) | ||
|
||
useCaseOut.isSolved shouldBe true | ||
verify(exactly = 1) { problemDao.selectProblemAnswer(any()) } | ||
verify(exactly = 1) { submitHistoryDao.insertSubmitHistory(any()) } | ||
} | ||
} | ||
|
||
`when`("제출 값과 문제 정답이 다를 경우") { | ||
val submissionVal = "1" | ||
val answer = "2" | ||
val useCaseIn = CheckProblemUseCaseIn(problemId = 1L, sub = submissionVal) | ||
val answerRecord = SelectProblemAnswerRecord(id = 1L, answer = answer, explanation = "해설입니다.") | ||
|
||
every { problemDao.selectProblemAnswer(any()) } returns answerRecord | ||
every { submitHistoryDao.insertSubmitHistory(any()) } returns 1L | ||
|
||
then("문제가 오답처리 된다") { | ||
val useCaseOut = useCase.execute(useCaseIn) | ||
|
||
useCaseOut.isSolved shouldBe false | ||
verify(exactly = 1) { problemDao.selectProblemAnswer(any()) } | ||
verify(exactly = 1) { submitHistoryDao.insertSubmitHistory(any()) } | ||
} | ||
} | ||
|
||
`when`("존재하지 않는 문제일 경우") { | ||
val useCaseIn = CheckProblemUseCaseIn(problemId = 1L, sub = "1") | ||
|
||
every { problemDao.selectProblemAnswer(any()) } returns null | ||
|
||
then("예외가 발생한다") { | ||
shouldThrow<Exception> { useCase.execute(useCaseIn) } | ||
verify(exactly = 1) { problemDao.selectProblemAnswer(any()) } | ||
} | ||
} | ||
} | ||
}) |
59 changes: 59 additions & 0 deletions
59
api/src/test/kotlin/com/few/api/domain/problem/usecase/ReadProblemUseCaseTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package com.few.api.domain.problem.usecase | ||
|
||
import com.few.api.domain.problem.usecase.dto.ReadProblemUseCaseIn | ||
import com.few.api.repo.dao.problem.ProblemDao | ||
import com.few.api.repo.dao.problem.record.SelectProblemRecord | ||
import com.few.api.repo.dao.problem.support.Content | ||
import com.few.api.repo.dao.problem.support.Contents | ||
import com.few.api.repo.dao.problem.support.ContentsJsonMapper | ||
import io.kotest.assertions.throwables.shouldThrow | ||
import io.kotest.core.spec.style.BehaviorSpec | ||
import io.mockk.every | ||
import io.mockk.mockk | ||
import io.mockk.verify | ||
|
||
class ReadProblemUseCaseTest : BehaviorSpec({ | ||
|
||
lateinit var problemDao: ProblemDao | ||
lateinit var contentsJsonMapper: ContentsJsonMapper | ||
lateinit var useCase: ReadProblemUseCase | ||
val useCaseIn = ReadProblemUseCaseIn(problemId = 1L) | ||
|
||
beforeContainer { | ||
problemDao = mockk<ProblemDao>() | ||
contentsJsonMapper = mockk<ContentsJsonMapper>() | ||
useCase = ReadProblemUseCase(problemDao, contentsJsonMapper) | ||
} | ||
|
||
given("문제를 조회할 상황에서") { | ||
`when`("문제가 존재할 경우") { | ||
val problemRecord = SelectProblemRecord(id = 1L, title = "title", contents = "{}") | ||
val contents = Contents( | ||
listOf( | ||
Content(number = 1, content = "{}"), | ||
Content(number = 2, content = "{}") | ||
) | ||
) | ||
|
||
every { problemDao.selectProblemContents(any()) } returns problemRecord | ||
every { contentsJsonMapper.toObject(any()) } returns contents | ||
|
||
then("정상적으로 실행되어야 한다") { | ||
useCase.execute(useCaseIn) | ||
|
||
verify(exactly = 1) { problemDao.selectProblemContents(any()) } | ||
verify(exactly = 1) { contentsJsonMapper.toObject(any()) } | ||
} | ||
} | ||
|
||
`when`("문제가 존재하지 않을 경우") { | ||
every { problemDao.selectProblemContents(any()) } returns null | ||
|
||
then("예외가 발생해야 한다") { | ||
shouldThrow<Exception> { useCase.execute(useCaseIn) } | ||
|
||
verify(exactly = 1) { problemDao.selectProblemContents(any()) } | ||
} | ||
} | ||
} | ||
}) |
112 changes: 112 additions & 0 deletions
112
api/src/test/kotlin/com/few/api/domain/subscription/usecase/SubscribeWorkbookUseCaseTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
package com.few.api.domain.subscription.usecase | ||
|
||
import com.few.api.domain.subscription.event.dto.WorkbookSubscriptionEvent | ||
import com.few.api.domain.subscription.service.MemberService | ||
import com.few.api.domain.subscription.service.dto.MemberIdOutDto | ||
import com.few.api.domain.subscription.usecase.dto.SubscribeWorkbookUseCaseIn | ||
import com.few.api.repo.dao.subscription.SubscriptionDao | ||
import com.few.api.repo.dao.subscription.record.WorkbookSubscriptionStatus | ||
import io.kotest.assertions.throwables.shouldThrow | ||
import io.kotest.core.spec.style.BehaviorSpec | ||
import io.mockk.every | ||
import io.mockk.mockk | ||
import io.mockk.verify | ||
import io.mockk.just | ||
import io.mockk.Runs | ||
import org.springframework.context.ApplicationEventPublisher | ||
|
||
class SubscribeWorkbookUseCaseTest : BehaviorSpec({ | ||
|
||
lateinit var subscriptionDao: SubscriptionDao | ||
lateinit var memberService: MemberService | ||
lateinit var applicationEventPublisher: ApplicationEventPublisher | ||
lateinit var useCase: SubscribeWorkbookUseCase | ||
val workbookId = 1L | ||
val useCaseIn = SubscribeWorkbookUseCaseIn(workbookId = workbookId, email = "[email protected]") | ||
|
||
beforeContainer { | ||
subscriptionDao = mockk<SubscriptionDao>() | ||
memberService = mockk<MemberService>() | ||
applicationEventPublisher = mockk<ApplicationEventPublisher>() | ||
useCase = SubscribeWorkbookUseCase(subscriptionDao, memberService, applicationEventPublisher) | ||
} | ||
|
||
given("구독 요청이 온 상황에서") { | ||
`when`("subscriptionStatus가 null일 경우") { | ||
val serviceOutDto = MemberIdOutDto(memberId = 1L) | ||
val event = WorkbookSubscriptionEvent(workbookId) | ||
|
||
every { memberService.readMemberId(any()) } returns null | ||
every { memberService.insertMember(any()) } returns serviceOutDto | ||
every { subscriptionDao.selectTopWorkbookSubscriptionStatus(any()) } returns null | ||
every { subscriptionDao.insertWorkbookSubscription(any()) } just Runs | ||
every { applicationEventPublisher.publishEvent(event) } answers { | ||
println("Mocking applicationEventPublisher.publishEvent(any()) was called") | ||
} | ||
|
||
then("신규 구독을 추가한다") { | ||
useCase.execute(useCaseIn) | ||
|
||
verify(exactly = 1) { memberService.insertMember(any()) } | ||
verify(exactly = 1) { subscriptionDao.insertWorkbookSubscription(any()) } | ||
verify(exactly = 0) { subscriptionDao.countWorkbookMappedArticles(any()) } | ||
verify(exactly = 0) { subscriptionDao.reSubscribeWorkbookSubscription(any()) } | ||
verify(exactly = 1) { applicationEventPublisher.publishEvent(event) } | ||
} | ||
} | ||
|
||
`when`("구독을 취소한 경우") { | ||
val day = 2 | ||
val lastDay = 3 | ||
val serviceOutDto = MemberIdOutDto(memberId = 1L) | ||
val subscriptionStatusRecord = WorkbookSubscriptionStatus(workbookId = workbookId, isActiveSub = false, day) | ||
val event = WorkbookSubscriptionEvent(workbookId) | ||
|
||
every { memberService.readMemberId(any()) } returns null | ||
every { memberService.insertMember(any()) } returns serviceOutDto | ||
every { subscriptionDao.selectTopWorkbookSubscriptionStatus(any()) } returns subscriptionStatusRecord | ||
every { subscriptionDao.countWorkbookMappedArticles(any()) } returns lastDay | ||
every { subscriptionDao.reSubscribeWorkbookSubscription(any()) } just Runs | ||
every { applicationEventPublisher.publishEvent(event) } answers { | ||
println("Mocking applicationEventPublisher.publishEvent(any()) was called") | ||
} | ||
|
||
then("재구독한다") { | ||
useCase.execute(useCaseIn) | ||
|
||
verify(exactly = 1) { memberService.insertMember(any()) } | ||
verify(exactly = 0) { subscriptionDao.insertWorkbookSubscription(any()) } | ||
verify(exactly = 1) { subscriptionDao.countWorkbookMappedArticles(any()) } | ||
verify(exactly = 1) { subscriptionDao.reSubscribeWorkbookSubscription(any()) } | ||
verify(exactly = 1) { applicationEventPublisher.publishEvent(event) } | ||
} | ||
} | ||
|
||
`when`("이미 구독하고 있을 경우") { | ||
val day = 2 | ||
val lastDay = 3 | ||
val serviceOutDto = MemberIdOutDto(memberId = 1L) | ||
val subscriptionStatusRecord = WorkbookSubscriptionStatus(workbookId = workbookId, isActiveSub = true, day) | ||
val event = WorkbookSubscriptionEvent(workbookId) | ||
|
||
every { memberService.readMemberId(any()) } returns null | ||
every { memberService.insertMember(any()) } returns serviceOutDto | ||
every { subscriptionDao.selectTopWorkbookSubscriptionStatus(any()) } returns subscriptionStatusRecord | ||
every { subscriptionDao.countWorkbookMappedArticles(any()) } returns lastDay | ||
every { subscriptionDao.reSubscribeWorkbookSubscription(any()) } just Runs | ||
every { applicationEventPublisher.publishEvent(event) } answers { | ||
println("Mocking applicationEventPublisher.publishEvent(any()) was called") | ||
} | ||
|
||
then("예외가 발생한다") { | ||
shouldThrow<Exception> { useCase.execute(useCaseIn) } | ||
|
||
verify(exactly = 1) { memberService.insertMember(any()) } | ||
verify(exactly = 0) { subscriptionDao.insertWorkbookSubscription(any()) } | ||
verify(exactly = 0) { subscriptionDao.countWorkbookMappedArticles(any()) } | ||
verify(exactly = 0) { subscriptionDao.reSubscribeWorkbookSubscription(any()) } | ||
verify(exactly = 0) { applicationEventPublisher.publishEvent(event) } | ||
} | ||
} | ||
} | ||
}) |
Oops, something went wrong.