diff --git a/.github/workflows/git-action-main.yml b/.github/workflows/git-action-main.yml index dba2260..5634c9c 100644 --- a/.github/workflows/git-action-main.yml +++ b/.github/workflows/git-action-main.yml @@ -2,15 +2,29 @@ name: meogo-main on: push: - branches: [ "main" ] + branches: ["main"] pull_request: - branches: [ "main" ] + branches: ["main"] workflow_dispatch: jobs: build: runs-on: ubuntu-latest + env: + SECRET_KEY: ${{ secrets.SECRET_KEY }} + AWS_ACCESS_KEY: ${{ secrets.AWS_ACCESS_KEY }} + AWS_SECRET_KEY: ${{ secrets.AWS_SECRET_KEY }} + S3_BUCKET: ${{ secrets.S3_BUCKET }} + FCM_URL: ${{ secrets.FCM_URL }} + CAREER_URL: ${{ secrets.CAREER_URL }} + CAREER_KEY: ${{ secrets.CAREER_KEY }} + ACCESS_EXP: ${{ secrets.ACCESS_EXP }} + REFRESH_EXP: ${{ secrets.REFRESH_EXP }} + DB_URL: ${{ secrets.DB_URL }} + DB_USERNAME: ${{ secrets.DB_USERNAME }} + DB_PASSWORD: ${{ secrets.PASSWORD }} + steps: - uses: actions/checkout@v3 @@ -19,11 +33,13 @@ jobs: with: java-version: '17' distribution: 'temurin' - + - name: Build Gradle uses: gradle/gradle-build-action@v2 with: arguments: | - build - --build-cache + clean build --no-daemon + + - name: Run tests with verbose output + run: ./gradlew test --debug diff --git a/build.gradle.kts b/build.gradle.kts index 159ad44..ad8d09f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,10 +1,10 @@ plugins { - kotlin("jvm") version "1.6.21" - kotlin("plugin.spring") version "1.9.25" + kotlin("jvm") version "1.9.24" + kotlin("plugin.spring") version "1.9.24" + kotlin("plugin.jpa") version "1.9.24" id("org.springframework.boot") version "2.7.16" id("io.spring.dependency-management") version "1.1.6" id("org.jlleitschuh.gradle.ktlint") version "11.5.1" - kotlin("plugin.jpa") version "1.6.21" } group = "org.meogo" @@ -42,10 +42,12 @@ dependencies { compileOnly("org.projectlombok:lombok") runtimeOnly("com.mysql:mysql-connector-j") annotationProcessor("org.projectlombok:lombok") + testImplementation("org.springframework.boot:spring-boot-starter-test") - testImplementation("org.jetbrains.kotlin:kotlin-test-junit5") - testImplementation("org.springframework.security:spring-security-test") - testRuntimeOnly("org.junit.platform:junit-platform-launcher") + testImplementation("org.mockito:mockito-core:5.2.0") + testImplementation("org.mockito.kotlin:mockito-kotlin:5.2.0") + testImplementation("org.junit.jupiter:junit-jupiter-api:5.8.2") + testImplementation("org.junit.jupiter:junit-jupiter-engine:5.8.2") } kotlin { diff --git a/src/main/kotlin/org/meogo/domain/bookmark/service/BookmarkService.kt b/src/main/kotlin/org/meogo/domain/bookmark/service/BookmarkService.kt index b13980c..e97aa42 100644 --- a/src/main/kotlin/org/meogo/domain/bookmark/service/BookmarkService.kt +++ b/src/main/kotlin/org/meogo/domain/bookmark/service/BookmarkService.kt @@ -3,7 +3,6 @@ package org.meogo.domain.bookmark.service import org.meogo.domain.bookmark.domain.Bookmark import org.meogo.domain.bookmark.domain.BookmarkRepository import org.meogo.domain.bookmark.exception.BookmarkNotFoundException -import org.meogo.domain.post.domain.PostRepository import org.meogo.domain.user.exception.UserNotFoundException import org.meogo.domain.user.facade.UserFacade import org.springframework.stereotype.Service @@ -13,8 +12,7 @@ import org.springframework.transaction.annotation.Transactional @Service class BookmarkService( private val bookmarkRepository: BookmarkRepository, - private val userFacade: UserFacade, - private val postRepository: PostRepository + private val userFacade: UserFacade ) { fun execute(schoolId: Int) { diff --git a/src/main/kotlin/org/meogo/global/utill/FcmUtil.kt b/src/main/kotlin/org/meogo/global/utill/FcmUtil.kt index 4ff1860..de7ab2e 100644 --- a/src/main/kotlin/org/meogo/global/utill/FcmUtil.kt +++ b/src/main/kotlin/org/meogo/global/utill/FcmUtil.kt @@ -15,8 +15,8 @@ class FcmUtil { private val firebase: FirebaseMessaging get() = FirebaseMessaging.getInstance() - fun sendMessage(fcmToken: List, title: String, message: String) { - val message = messageSetting(fcmToken, title, message) + fun sendMessage(fcmToken: List, title: String, content: String) { + val message = messageSetting(fcmToken, title, content) try { firebase.sendMulticastAsync(message) @@ -25,19 +25,19 @@ class FcmUtil { } } - fun messageSetting(fcmToken: List, title: String, message: String) = + fun messageSetting(fcmToken: List, title: String, content: String) = MulticastMessage.builder() .addAllTokens(fcmToken) .setNotification( Notification.builder() .setTitle(title) - .setBody(message) + .setBody(content) .build() ) .setAndroidConfig( AndroidConfig.builder() .putData("title", title) - .putData("body", message) + .putData("body", content) .build() ) .setApnsConfig( @@ -45,7 +45,7 @@ class FcmUtil { .setAps( Aps.builder() .putCustomData("title", title) - .putCustomData("body", message) + .putCustomData("body", content) .build() ).build() ).build()!! diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 77a007c..ae26458 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,25 +1,24 @@ spring: - spring: - config.activate.on-profile: default - datasource: - driver-class-name: com.mysql.cj.jdbc.Driver - url: ${DB_URL} - username: ${DB_USERNAME} - password: ${DB_PASSWORD} - hikari: - maxLifetime: 580000 - jpa: + config.activate.on-profile: default +datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: ${DB_URL} + username: ${DB_USERNAME} + password: ${DB_PASSWORD} + hikari: + maxLifetime: 580000 +jpa: + hibernate: + ddl-auto: update + show-sql: true + properties: hibernate: - ddl-auto: update - show-sql: true - properties: - hibernate: - format_sql: true - open-in-view: false - database: mysql + format_sql: true + open-in-view: false + database: mysql - jackson: - property-naming-strategy: SNAKE_CASE +jackson: + property-naming-strategy: SNAKE_CASE auth: jwt: @@ -38,7 +37,7 @@ cloud: default-image: ${DEFAULT_IMAGE} bucket: ${S3_BUCKET} region: - static: ap-northeast-2 + static: ap-northeast-2 stack: auto: false diff --git a/src/test/kotlin/org/meogo/MeogoBackendApplicationTests.kt b/src/test/kotlin/org/meogo/MeogoBackendApplicationTests.kt new file mode 100644 index 0000000..07aecaf --- /dev/null +++ b/src/test/kotlin/org/meogo/MeogoBackendApplicationTests.kt @@ -0,0 +1,14 @@ +package org.meogo + +import org.junit.jupiter.api.Test +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.test.context.ActiveProfiles + +@SpringBootTest +@ActiveProfiles("test") +class MeogoBackendApplicationTests { + + @Test + fun contextLoads() { + } +} diff --git a/src/test/kotlin/org/meogo/domain/bookmark/service/BookmarkServiceTest.kt b/src/test/kotlin/org/meogo/domain/bookmark/service/BookmarkServiceTest.kt new file mode 100644 index 0000000..16b8c32 --- /dev/null +++ b/src/test/kotlin/org/meogo/domain/bookmark/service/BookmarkServiceTest.kt @@ -0,0 +1,114 @@ +package org.meogo.domain.bookmark.service + +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows +import org.junit.jupiter.api.extension.ExtendWith +import org.meogo.domain.bookmark.domain.Bookmark +import org.meogo.domain.bookmark.domain.BookmarkRepository +import org.meogo.domain.bookmark.exception.BookmarkNotFoundException +import org.meogo.domain.user.domain.User +import org.meogo.domain.user.domain.UserRole +import org.meogo.domain.user.facade.UserFacade +import org.mockito.InjectMocks +import org.mockito.Mock +import org.mockito.junit.jupiter.MockitoExtension +import org.mockito.kotlin.any +import org.mockito.kotlin.verify +import org.mockito.kotlin.whenever +import org.springframework.test.context.ActiveProfiles + +@ExtendWith(MockitoExtension::class) +@ActiveProfiles("test") +class BookmarkServiceTest { + + @Mock + private lateinit var bookmarkRepository: BookmarkRepository + + @Mock + private lateinit var userFacade: UserFacade + + @InjectMocks + private lateinit var bookmarkService: BookmarkService + + private lateinit var user: User + private val schoolId = 123 + + @BeforeEach + fun setUp() { + user = User( + name = "test", + accountId = "test", + password = "password", + role = UserRole.USER, + profile = "default" + ) + + whenever(userFacade.currentUser()).thenReturn(user) + } + + @Test + fun `북마크 저장`() { + // given & when + bookmarkService.execute(schoolId) + + // then + verify(bookmarkRepository).save(any()) + } + + @Test + fun `북마크 리스트 조회`() { + // given + val bookmark1 = Bookmark(schoolId = 1, user = user) + val bookmark2 = Bookmark(schoolId = 2, user = user) + + whenever(bookmarkRepository.findAllByUser(user)).thenReturn(listOf(bookmark1, bookmark2)) + + // when + val bookmarkedSchools = bookmarkService.queryBookmarkedSchool() + + // then + assertEquals(2, bookmarkedSchools.size) + assertEquals(1, bookmarkedSchools[0]) + assertEquals(2, bookmarkedSchools[1]) + } + + @Test + fun `북마크 여부 확인`() { + // given + val bookmark = Bookmark(schoolId = schoolId, user = user) + whenever(bookmarkRepository.existsBySchoolIdAndUser(bookmark.schoolId, bookmark.user)).thenReturn(true) + + // when + val isBookmarked = bookmarkService.queryIsBookmarked(schoolId) + + // then + assertEquals(true, isBookmarked) + } + + @Test + fun `북마크 삭제 성공`() { + // given + val bookmark = Bookmark(schoolId = schoolId, user = user) + + whenever(bookmarkRepository.findBySchoolIdAndUser(schoolId, user)).thenReturn(bookmark) + + // when + bookmarkService.deleteBookmark(schoolId) + + // then + verify(bookmarkRepository).delete(bookmark) + } + + @Test + fun `북마크 삭제 실패`() { + // given + whenever(bookmarkRepository.findBySchoolIdAndUser(schoolId, user)).thenReturn(null) + + // when & then + assertThrows { + bookmarkService.deleteBookmark(schoolId) + } + } +} diff --git a/src/test/resources/application-test.yml b/src/test/resources/application-test.yml new file mode 100644 index 0000000..39894d1 --- /dev/null +++ b/src/test/resources/application-test.yml @@ -0,0 +1,56 @@ +spring: + config: + activate: + on-profile: test + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: ${DB_URL} + username: ${DB_USERNAME} + password: ${DB_PASSWORD} + hikari: + maxLifetime: 580000 + jpa: + hibernate: + ddl-auto: update + show-sql: true + properties: + hibernate: + format_sql: true + open-in-view: false + database: mysql + + jackson: + property-naming-strategy: SNAKE_CASE + +auth: + jwt: + secretKey: ${SECRET_KEY} + accessExp: ${ACCESS_EXP} + refreshExp: ${REFRESH_EXP} + header: "Authorization" + prefix: "Bearer " + +cloud: + aws: + credentials: + access-key: ${AWS_ACCESS_KEY} + secret-key: ${AWS_SECRET_KEY} + s3: + default-image: ${DEFAULT_IMAGE} + bucket: ${S3_BUCKET} + region: + static: ap-northeast-2 + stack: + auto: false + +firebase: + url: ${FCM_URL} + +url: + career: ${CAREER_URL} + +open-feign: + career-key: ${CAREER_KEY} + +server: + port: 8989