diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index db51f9120..cc12ba8ef 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -23,6 +23,9 @@ android:theme="@style/Theme.Naaga" android:usesCleartextTraffic="true" tools:targetApi="33"> + + android:exported="false" + android:screenOrientation="portrait" /> + android:exported="false" + android:screenOrientation="portrait" /> + android:exported="false" + android:screenOrientation="portrait" /> + android:exported="false" + android:screenOrientation="portrait" /> + android:exported="false" + android:screenOrientation="portrait" /> + android:exported="false" + android:screenOrientation="portrait" /> + android:exported="false" + android:screenOrientation="portrait" /> + android:exported="false" + android:screenOrientation="portrait" /> + android:exported="false" + android:screenOrientation="portrait" /> + android:exported="false" + android:screenOrientation="portrait" /> diff --git a/android/app/src/main/java/com/now/naaga/data/remote/dto/NicknameDto.kt b/android/app/src/main/java/com/now/naaga/data/remote/dto/NicknameDto.kt new file mode 100644 index 000000000..cbd176ee3 --- /dev/null +++ b/android/app/src/main/java/com/now/naaga/data/remote/dto/NicknameDto.kt @@ -0,0 +1,10 @@ +package com.now.naaga.data.remote.dto + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class NicknameDto( + @SerialName("nickname") + val nickname: String, +) diff --git a/android/app/src/main/java/com/now/naaga/data/remote/retrofit/service/ProfileService.kt b/android/app/src/main/java/com/now/naaga/data/remote/retrofit/service/ProfileService.kt new file mode 100644 index 000000000..e9b82a30d --- /dev/null +++ b/android/app/src/main/java/com/now/naaga/data/remote/retrofit/service/ProfileService.kt @@ -0,0 +1,18 @@ +package com.now.naaga.data.remote.retrofit.service + +import com.now.naaga.data.remote.dto.NicknameDto +import com.now.naaga.data.remote.dto.PlayerDto +import retrofit2.Response +import retrofit2.http.Body +import retrofit2.http.GET +import retrofit2.http.PATCH + +interface ProfileService { + @GET("/profiles/my") + suspend fun getProfile(): Response + + @PATCH("/profiles/my") + suspend fun modifyNickname( + @Body nicknameDto: NicknameDto, + ): Response +} diff --git a/android/app/src/main/java/com/now/naaga/data/repository/DefaultProfileRepository.kt b/android/app/src/main/java/com/now/naaga/data/repository/DefaultProfileRepository.kt new file mode 100644 index 000000000..a2fe8165f --- /dev/null +++ b/android/app/src/main/java/com/now/naaga/data/repository/DefaultProfileRepository.kt @@ -0,0 +1,23 @@ +package com.now.naaga.data.repository + +import com.now.domain.model.Player +import com.now.domain.repository.ProfileRepository +import com.now.naaga.data.mapper.toDomain +import com.now.naaga.data.remote.dto.NicknameDto +import com.now.naaga.data.remote.retrofit.service.ProfileService +import com.now.naaga.util.extension.getValueOrThrow + +class DefaultProfileRepository( + private val profileService: ProfileService, +) : ProfileRepository { + override suspend fun fetchProfile(): Player { + val response = profileService.getProfile().getValueOrThrow() + return response.toDomain() + } + + override suspend fun modifyNickname(nickname: String): String { + val nicknameDto = NicknameDto(nickname) + val response = profileService.modifyNickname(nicknameDto).getValueOrThrow() + return response.nickname + } +} diff --git a/android/app/src/main/java/com/now/naaga/di/RepositoryModule.kt b/android/app/src/main/java/com/now/naaga/di/RepositoryModule.kt index a05423df3..14f66f119 100644 --- a/android/app/src/main/java/com/now/naaga/di/RepositoryModule.kt +++ b/android/app/src/main/java/com/now/naaga/di/RepositoryModule.kt @@ -4,6 +4,7 @@ import com.now.domain.repository.AdventureRepository import com.now.domain.repository.AuthRepository import com.now.domain.repository.LetterRepository import com.now.domain.repository.PlaceRepository +import com.now.domain.repository.ProfileRepository import com.now.domain.repository.RankRepository import com.now.domain.repository.StatisticsRepository import com.now.naaga.data.local.AuthDataSource @@ -11,12 +12,14 @@ import com.now.naaga.data.remote.retrofit.service.AdventureService import com.now.naaga.data.remote.retrofit.service.AuthService import com.now.naaga.data.remote.retrofit.service.LetterService import com.now.naaga.data.remote.retrofit.service.PlaceService +import com.now.naaga.data.remote.retrofit.service.ProfileService import com.now.naaga.data.remote.retrofit.service.RankService import com.now.naaga.data.remote.retrofit.service.StatisticsService import com.now.naaga.data.repository.DefaultAdventureRepository import com.now.naaga.data.repository.DefaultAuthRepository import com.now.naaga.data.repository.DefaultLetterRepository import com.now.naaga.data.repository.DefaultPlaceRepository +import com.now.naaga.data.repository.DefaultProfileRepository import com.now.naaga.data.repository.DefaultRankRepository import com.now.naaga.data.repository.DefaultStatisticsRepository import dagger.Module @@ -55,4 +58,9 @@ class RepositoryModule { @Provides fun provideLetterRepository(letterService: LetterService): LetterRepository = DefaultLetterRepository(letterService) + + @Singleton + @Provides + fun provideProfileRepository(profileService: ProfileService): ProfileRepository = + DefaultProfileRepository(profileService) } diff --git a/android/app/src/main/java/com/now/naaga/di/ServiceModule.kt b/android/app/src/main/java/com/now/naaga/di/ServiceModule.kt index 340e12d02..0920fdb49 100644 --- a/android/app/src/main/java/com/now/naaga/di/ServiceModule.kt +++ b/android/app/src/main/java/com/now/naaga/di/ServiceModule.kt @@ -7,6 +7,7 @@ import com.now.naaga.data.remote.retrofit.service.AdventureService import com.now.naaga.data.remote.retrofit.service.AuthService import com.now.naaga.data.remote.retrofit.service.LetterService import com.now.naaga.data.remote.retrofit.service.PlaceService +import com.now.naaga.data.remote.retrofit.service.ProfileService import com.now.naaga.data.remote.retrofit.service.RankService import com.now.naaga.data.remote.retrofit.service.StatisticsService import dagger.Module @@ -61,4 +62,8 @@ class ServiceModule { @Singleton @Provides fun provideLetterService(retrofit: Retrofit): LetterService = retrofit.create(LetterService::class.java) + + @Singleton + @Provides + fun provideProfileService(retrofit: Retrofit): ProfileService = retrofit.create(ProfileService::class.java) } diff --git a/android/app/src/main/java/com/now/naaga/presentation/common/dialog/LetterReadDialog.kt b/android/app/src/main/java/com/now/naaga/presentation/common/dialog/LetterReadDialog.kt index cd35bee26..7f0553647 100644 --- a/android/app/src/main/java/com/now/naaga/presentation/common/dialog/LetterReadDialog.kt +++ b/android/app/src/main/java/com/now/naaga/presentation/common/dialog/LetterReadDialog.kt @@ -8,10 +8,13 @@ import android.view.View import android.view.ViewGroup import androidx.fragment.app.DialogFragment import com.now.naaga.databinding.DialogReadLetterBinding +import com.now.naaga.presentation.uimodel.model.LetterUiModel import com.now.naaga.util.dpToPx import com.now.naaga.util.getWidthProportionalToDevice +import java.time.LocalDateTime +import java.time.format.DateTimeFormatter -class LetterReadDialog(private val content: String) : DialogFragment() { +class LetterReadDialog(private val content: LetterUiModel) : DialogFragment() { private lateinit var binding: DialogReadLetterBinding override fun onCreateView( @@ -39,10 +42,18 @@ class LetterReadDialog(private val content: String) : DialogFragment() { private fun setContent() { binding.letter = content + binding.tvDialogLetterDate.text = getFormattedDate() + } + + private fun getFormattedDate(): String { + val serverLocalDateTime = LocalDateTime.parse(content.registerDate, DateTimeFormatter.ISO_DATE_TIME) + val outputFormatter = DateTimeFormatter.ofPattern(DATE_FORMAT_PATTERN) + return serverLocalDateTime.format(outputFormatter) } companion object { private const val WIDTH_RATE = 0.78f private const val HEIGHT = 430 + private const val DATE_FORMAT_PATTERN = "yyyy-MM-dd" } } diff --git a/android/app/src/main/java/com/now/naaga/presentation/mypage/MyPageActivity.kt b/android/app/src/main/java/com/now/naaga/presentation/mypage/MyPageActivity.kt index 516b77f63..1c50e185b 100644 --- a/android/app/src/main/java/com/now/naaga/presentation/mypage/MyPageActivity.kt +++ b/android/app/src/main/java/com/now/naaga/presentation/mypage/MyPageActivity.kt @@ -3,6 +3,7 @@ package com.now.naaga.presentation.mypage import android.content.Context import android.content.Intent import android.os.Bundle +import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity import com.now.domain.model.Statistics @@ -14,6 +15,7 @@ import com.now.naaga.data.throwable.DataThrowable import com.now.naaga.databinding.ActivityMyPageBinding import com.now.naaga.presentation.adventurehistory.AdventureHistoryActivity import com.now.naaga.presentation.mypage.statistics.MyPageStatisticsAdapter +import com.now.naaga.presentation.profile.ProfileActivity import com.now.naaga.presentation.uimodel.model.StatisticsUiModel import com.now.naaga.util.extension.showToast import dagger.hilt.android.AndroidEntryPoint @@ -23,6 +25,14 @@ class MyPageActivity : AppCompatActivity(), AnalyticsDelegate by DefaultAnalytic private lateinit var binding: ActivityMyPageBinding private val viewModel: MyPageViewModel by viewModels() + private val myPageActivityLauncher = + registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { + if (it.resultCode == RESULT_OK) { + val nickname = it.data?.getStringExtra(NICKNAME_KEY) ?: "" + binding.tvMypageNickname.text = nickname + } + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityMyPageBinding.inflate(layoutInflater) @@ -48,10 +58,14 @@ class MyPageActivity : AppCompatActivity(), AnalyticsDelegate by DefaultAnalytic val intent = AdventureHistoryActivity.getIntent(this) startActivity(intent) } + binding.ivMypageProfileModify.setOnClickListener { + val intent = ProfileActivity.getIntent(this) + myPageActivityLauncher.launch(intent) + } } private fun fetchData() { - viewModel.fetchRank() + viewModel.fetchProfile() viewModel.fetchStatistics() viewModel.fetchPlaces() } @@ -82,8 +96,16 @@ class MyPageActivity : AppCompatActivity(), AnalyticsDelegate by DefaultAnalytic } companion object { + private const val NICKNAME_KEY = "nickname" + fun getIntent(context: Context): Intent { return Intent(context, MyPageActivity::class.java) } + + fun getIntent(context: Context, nickname: String): Intent { + return Intent(context, MyPageActivity::class.java).apply { + putExtra(NICKNAME_KEY, nickname) + } + } } } diff --git a/android/app/src/main/java/com/now/naaga/presentation/mypage/MyPageViewModel.kt b/android/app/src/main/java/com/now/naaga/presentation/mypage/MyPageViewModel.kt index 5a70439ea..e2f4122b4 100644 --- a/android/app/src/main/java/com/now/naaga/presentation/mypage/MyPageViewModel.kt +++ b/android/app/src/main/java/com/now/naaga/presentation/mypage/MyPageViewModel.kt @@ -5,12 +5,12 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.now.domain.model.Place -import com.now.domain.model.Rank +import com.now.domain.model.Player import com.now.domain.model.Statistics import com.now.domain.model.type.OrderType import com.now.domain.model.type.SortType import com.now.domain.repository.PlaceRepository -import com.now.domain.repository.RankRepository +import com.now.domain.repository.ProfileRepository import com.now.domain.repository.StatisticsRepository import com.now.naaga.data.throwable.DataThrowable import dagger.hilt.android.lifecycle.HiltViewModel @@ -20,12 +20,12 @@ import javax.inject.Inject @HiltViewModel class MyPageViewModel @Inject constructor( - private val rankRepository: RankRepository, + private val profileRepository: ProfileRepository, private val statisticsRepository: StatisticsRepository, private val placeRepository: PlaceRepository, ) : ViewModel() { - private val _rank = MutableLiveData() - val rank: LiveData = _rank + private val _profile = MutableLiveData() + val profile: LiveData = _profile private val _statistics = MutableLiveData() val statistics: LiveData = _statistics @@ -36,12 +36,12 @@ class MyPageViewModel @Inject constructor( private val _throwable = MutableLiveData() val throwable: LiveData = _throwable - fun fetchRank() { + fun fetchProfile() { viewModelScope.launch { runCatching { - rankRepository.getMyRank() - }.onSuccess { rank -> - _rank.value = rank + profileRepository.fetchProfile() + }.onSuccess { profile -> + _profile.value = profile }.onFailure { setThrowable(it) } diff --git a/android/app/src/main/java/com/now/naaga/presentation/onadventure/NaverMapSettingDelegate.kt b/android/app/src/main/java/com/now/naaga/presentation/onadventure/NaverMapSettingDelegate.kt index 6f02b328a..8214d8d98 100644 --- a/android/app/src/main/java/com/now/naaga/presentation/onadventure/NaverMapSettingDelegate.kt +++ b/android/app/src/main/java/com/now/naaga/presentation/onadventure/NaverMapSettingDelegate.kt @@ -130,25 +130,15 @@ class DefaultNaverMapSettingDelegate() : NaverMapSettingDelegate, DefaultLifecyc override fun addLetter(letter: LetterPreview, action: (id: Long) -> Unit) { Marker().apply { position = LatLng(letter.coordinate.latitude, letter.coordinate.longitude) - icon = selectLetterIcon(letter.isNearBy) - if (letter.isNearBy) { - setOnSingleClickListener { - action(letter.id) - } + icon = OverlayImage.fromResource(R.drawable.ic_letter) + setOnSingleClickListener { + action(letter.id) } map = naverMap letterMarkers.add(this) } } - private fun selectLetterIcon(isNearBy: Boolean): OverlayImage { - return if (isNearBy) { - OverlayImage.fromResource(R.drawable.ic_letter) - } else { - OverlayImage.fromResource(R.drawable.ic_letter_preview) - } - } - override fun removeLetters() { letterMarkers.forEach { letterMarker -> letterMarker.map = null diff --git a/android/app/src/main/java/com/now/naaga/presentation/onadventure/OnAdventureActivity.kt b/android/app/src/main/java/com/now/naaga/presentation/onadventure/OnAdventureActivity.kt index 401c6beda..2f8880684 100644 --- a/android/app/src/main/java/com/now/naaga/presentation/onadventure/OnAdventureActivity.kt +++ b/android/app/src/main/java/com/now/naaga/presentation/onadventure/OnAdventureActivity.kt @@ -34,6 +34,7 @@ import com.now.naaga.presentation.common.dialog.PolaroidDialog import com.now.naaga.presentation.uimodel.mapper.toDomain import com.now.naaga.presentation.uimodel.mapper.toUi import com.now.naaga.presentation.uimodel.model.AdventureUiModel +import com.now.naaga.presentation.uimodel.model.LetterUiModel import com.now.naaga.util.extension.getParcelableCompat import com.now.naaga.util.extension.showSnackbar import com.now.naaga.util.extension.showToast @@ -110,6 +111,7 @@ class OnAdventureActivity : private fun subscribe() { viewModel.startCoordinate.observe(this) { beginAdventure(it) + viewModel.fetchLetters() } viewModel.adventure.observe(this) { isAdventureDone(it.adventureStatus) @@ -125,15 +127,15 @@ class OnAdventureActivity : viewModel.isSendLetterSuccess.observe(this) { supportFragmentManager.findFragmentByTag(LetterSendDialog.TAG)?.onDestroyView() when (it) { - true -> { binding.root.showSnackbar(getString(R.string.OnAdventure_send_letter_success)) } - false -> { binding.root.showSnackbar(getString(R.string.OnAdventure_send_letter_fail)) } + true -> binding.root.showSnackbar(getString(R.string.OnAdventure_send_letter_success)) + false -> binding.root.showSnackbar(getString(R.string.OnAdventure_send_letter_fail)) } } - viewModel.letters.observe(this) { + viewModel.nearbyLetters.observe(this) { drawLetters(it) } viewModel.letter.observe(this) { - showLetterReadDialog(it.message) + showLetterReadDialog(it) } viewModel.throwable.observe(this) { throwable: DataThrowable -> logServerError(ON_ADVENTURE_GAME, throwable.code, throwable.message.toString()) @@ -149,8 +151,7 @@ class OnAdventureActivity : } OnAdventureViewModel.TRY_COUNT_OVER -> showToast(getString(R.string.onAdventure_try_count_over)) - - DataThrowable.NETWORK_THROWABLE_CODE -> { showToast(getString(R.string.network_error_message)) } + DataThrowable.NETWORK_THROWABLE_CODE -> showToast(getString(R.string.network_error_message)) else -> shortSnackbar(throwable.message ?: return@observe) } @@ -248,7 +249,7 @@ class OnAdventureActivity : } } - private fun showLetterReadDialog(content: String) { + private fun showLetterReadDialog(content: LetterUiModel) { LetterReadDialog(content).show(supportFragmentManager, LETTER) } diff --git a/android/app/src/main/java/com/now/naaga/presentation/onadventure/OnAdventureViewModel.kt b/android/app/src/main/java/com/now/naaga/presentation/onadventure/OnAdventureViewModel.kt index f902c648f..03466ebf3 100644 --- a/android/app/src/main/java/com/now/naaga/presentation/onadventure/OnAdventureViewModel.kt +++ b/android/app/src/main/java/com/now/naaga/presentation/onadventure/OnAdventureViewModel.kt @@ -3,7 +3,6 @@ package com.now.naaga.presentation.onadventure import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel -import androidx.lifecycle.liveData import androidx.lifecycle.map import androidx.lifecycle.viewModelScope import com.now.domain.model.Adventure @@ -47,19 +46,8 @@ class OnAdventureViewModel @Inject constructor( private val _lastHint = MutableLiveData() val lastHint: LiveData = _lastHint - val letters: LiveData> = liveData { - while (true) { - myCoordinate.value?.let { coordinate -> - emit( - letterRepository.fetchNearbyLetters( - latitude = coordinate.latitude, - longitude = coordinate.longitude, - ).map { it.copy(isNearBy = coordinate.isNearBy(it.coordinate)) }, - ) - } ?: emit(emptyList()) - delay(5000) - } - } + private val _nearbyLetters = MutableLiveData>() + val nearbyLetters: LiveData> = _nearbyLetters private val _letter = MutableLiveData() val letter: LiveData = _letter @@ -102,6 +90,22 @@ class OnAdventureViewModel @Inject constructor( } } + fun fetchLetters() { + viewModelScope.launch { + while (true) { + val coordinate = requireNotNull(myCoordinate.value) { "나의 좌표가 null 입니다." } + runCatching { + letterRepository.fetchNearbyLetters(coordinate.latitude, coordinate.longitude) + }.onSuccess { + _nearbyLetters.value = it + }.onFailure { + setThrowable(it) + } + delay(5000L) + } + } + } + fun openHint() { if (isAllHintsUsed()) { setThrowable(hintThrowable) @@ -148,11 +152,13 @@ class OnAdventureViewModel @Inject constructor( _adventure.value = adventure.value?.copy(adventureStatus = AdventureStatus.DONE) _throwable.value = throwable } + NOT_ARRIVED -> { val currentRemainingTryCount = adventure.value?.remainingTryCount ?: return _adventure.value = adventure.value?.copy(remainingTryCount = currentRemainingTryCount - 1) _throwable.value = throwable } + else -> { _throwable.value = throwable } diff --git a/android/app/src/main/java/com/now/naaga/presentation/profile/ProfileActivity.kt b/android/app/src/main/java/com/now/naaga/presentation/profile/ProfileActivity.kt new file mode 100644 index 000000000..f7b780bd0 --- /dev/null +++ b/android/app/src/main/java/com/now/naaga/presentation/profile/ProfileActivity.kt @@ -0,0 +1,60 @@ +package com.now.naaga.presentation.profile + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import androidx.activity.viewModels +import androidx.appcompat.app.AppCompatActivity +import com.now.naaga.R +import com.now.naaga.databinding.ActivityProfileBinding +import com.now.naaga.presentation.mypage.MyPageActivity +import com.now.naaga.util.extension.showToast +import dagger.hilt.android.AndroidEntryPoint + +@AndroidEntryPoint +class ProfileActivity : AppCompatActivity() { + private lateinit var binding: ActivityProfileBinding + private val viewModel: ProfileViewModel by viewModels() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityProfileBinding.inflate(layoutInflater) + setContentView(binding.root) + binding.lifecycleOwner = this + binding.viewModel = viewModel + subscribe() + setClickListeners() + } + + private fun subscribe() { + viewModel.modifyStatus.observe(this) { status -> + if (status) { + showToast(getString(R.string.profile_modify_success_message)) + setResult(RESULT_OK, MyPageActivity.getIntent(this, viewModel.nickname.value.toString())) + finish() + } + } + viewModel.throwable.observe(this) { + showToast(getString(R.string.profile_modify_fail_message)) + } + } + + private fun setClickListeners() { + binding.ivProfileBack.setOnClickListener { + finish() + } + binding.btnProfileNicknameModify.setOnClickListener { + if (viewModel.isFormValid()) { + viewModel.modifyNickname() + } else { + showToast(getString(R.string.profile_no_content_message)) + } + } + } + + companion object { + fun getIntent(context: Context): Intent { + return Intent(context, ProfileActivity::class.java) + } + } +} diff --git a/android/app/src/main/java/com/now/naaga/presentation/profile/ProfileViewModel.kt b/android/app/src/main/java/com/now/naaga/presentation/profile/ProfileViewModel.kt new file mode 100644 index 000000000..3951c6877 --- /dev/null +++ b/android/app/src/main/java/com/now/naaga/presentation/profile/ProfileViewModel.kt @@ -0,0 +1,55 @@ +package com.now.naaga.presentation.profile + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.now.domain.repository.ProfileRepository +import com.now.naaga.data.throwable.DataThrowable +import com.now.naaga.data.throwable.DataThrowable.NetworkThrowable +import com.now.naaga.data.throwable.DataThrowable.PlayerThrowable +import com.now.naaga.data.throwable.DataThrowable.UniversalThrowable +import com.now.naaga.util.singleliveevent.MutableSingleLiveData +import com.now.naaga.util.singleliveevent.SingleLiveData +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.launch +import java.io.IOException +import javax.inject.Inject + +@HiltViewModel +class ProfileViewModel @Inject constructor( + private val profileRepository: ProfileRepository, +) : ViewModel() { + + val nickname = MutableLiveData() + + private val _modifyStatus = MutableSingleLiveData() + val modifyStatus: SingleLiveData = _modifyStatus + + private val _throwable = MutableLiveData() + val throwable: LiveData = _throwable + + fun modifyNickname() { + viewModelScope.launch { + runCatching { + profileRepository.modifyNickname(nickname.value.toString()) + }.onSuccess { + _modifyStatus.setValue(true) + }.onFailure { + setThrowable(it) + } + } + } + + fun isFormValid(): Boolean { + return nickname.value != null + } + + private fun setThrowable(throwable: Throwable) { + when (throwable) { + is IOException -> _throwable.value = NetworkThrowable() + is UniversalThrowable -> _throwable.value = throwable + is PlayerThrowable -> _throwable.value = throwable + } + } +} diff --git a/android/app/src/main/res/drawable/ic_letter_preview.xml b/android/app/src/main/res/drawable/ic_letter_preview.xml deleted file mode 100644 index 4d0547d38..000000000 --- a/android/app/src/main/res/drawable/ic_letter_preview.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - diff --git a/android/app/src/main/res/drawable/ic_profile_modify.xml b/android/app/src/main/res/drawable/ic_profile_modify.xml new file mode 100644 index 000000000..faddfce42 --- /dev/null +++ b/android/app/src/main/res/drawable/ic_profile_modify.xml @@ -0,0 +1,5 @@ + + + diff --git a/android/app/src/main/res/drawable/rect_border.xml b/android/app/src/main/res/drawable/rect_border.xml new file mode 100644 index 000000000..b90be845e --- /dev/null +++ b/android/app/src/main/res/drawable/rect_border.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/android/app/src/main/res/layout/activity_my_page.xml b/android/app/src/main/res/layout/activity_my_page.xml index 57ab97459..35663c5be 100644 --- a/android/app/src/main/res/layout/activity_my_page.xml +++ b/android/app/src/main/res/layout/activity_my_page.xml @@ -36,14 +36,12 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="@dimen/space_default_large" - android:layout_marginBottom="@dimen/space_default_medium" android:ellipsize="end" android:includeFontPadding="false" android:maxLines="1" - android:text="@{viewModel.rank.player.nickname}" + android:text="@{viewModel.profile.nickname}" android:textColor="@color/white" android:textSize="52sp" - app:layout_constraintBottom_toTopOf="@id/rv_mypage_statistics" app:layout_constraintEnd_toEndOf="@id/g_mypage" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/iv_mypage_back" @@ -53,25 +51,25 @@ android:id="@+id/btn_mypage_adventure_history" android:layout_width="0dp" android:layout_height="wrap_content" - android:layout_marginEnd="20dp" + android:layout_marginTop="@dimen/space_default_medium" + android:layout_marginHorizontal="24dp" android:paddingVertical="16dp" android:text="@string/mypage_adventure_record" - android:textSize="16sp" + android:textSize="24sp" app:radius="8dp" app:buttonColor="yellow" - app:layout_constraintBottom_toBottomOf="@id/tv_mypage_nickname" + app:layout_constraintTop_toBottomOf="@id/rv_mypage_statistics" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="@id/g_mypage" - app:layout_constraintTop_toTopOf="@id/tv_mypage_nickname" /> + app:layout_constraintBottom_toTopOf="@id/customGrid_mypage_places" + app:layout_constraintStart_toStartOf="parent" /> + app:layout_constraintTop_toBottomOf="@id/btn_mypage_adventure_history" /> + + diff --git a/android/app/src/main/res/layout/activity_profile.xml b/android/app/src/main/res/layout/activity_profile.xml new file mode 100644 index 000000000..eaf8c79f3 --- /dev/null +++ b/android/app/src/main/res/layout/activity_profile.xml @@ -0,0 +1,107 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/res/layout/activity_upload.xml b/android/app/src/main/res/layout/activity_upload.xml index 7058e7f08..337f7e5d8 100644 --- a/android/app/src/main/res/layout/activity_upload.xml +++ b/android/app/src/main/res/layout/activity_upload.xml @@ -106,14 +106,15 @@ android:layout_height="wrap_content" android:layout_marginTop="@dimen/space_default_large" android:autofillHints="no" + android:backgroundTint="@color/light_gray" android:ellipsize="end" android:hint="@string/upload_photo_title_hint" - android:textColorHint="@color/white" android:inputType="text" android:maxLines="1" android:text="@={viewModel.name}" android:textAlignment="textEnd" android:textColor="@color/white" + android:textColorHint="@color/main_gray_opacity_medium" android:textSize="24sp" app:layout_constraintEnd_toEndOf="@id/v_upload_divide_line_1" app:layout_constraintStart_toStartOf="@id/v_upload_divide_line_1" diff --git a/android/app/src/main/res/layout/dialog_read_letter.xml b/android/app/src/main/res/layout/dialog_read_letter.xml index d9bdcb431..510e55d00 100644 --- a/android/app/src/main/res/layout/dialog_read_letter.xml +++ b/android/app/src/main/res/layout/dialog_read_letter.xml @@ -1,11 +1,12 @@ - + type="com.now.naaga.presentation.uimodel.model.LetterUiModel" /> + app:layout_constraintTop_toBottomOf="@id/iv_dialog_send_letter_icon" /> + app:layout_constraintTop_toBottomOf="@id/iv_dialog_send_letter_icon" + app:layout_constraintVertical_bias="0.475" /> + + + + diff --git a/android/app/src/main/res/layout/rv_mypage_item_adventure.xml b/android/app/src/main/res/layout/rv_mypage_item_adventure.xml index aebfee68b..acfc614e6 100644 --- a/android/app/src/main/res/layout/rv_mypage_item_adventure.xml +++ b/android/app/src/main/res/layout/rv_mypage_item_adventure.xml @@ -71,7 +71,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="@dimen/space_default_medium" - android:layout_marginEnd="@dimen/space_default_large" + android:layout_marginEnd="32dp" android:text="@string/mypage_item_adventure_count_suffix" android:textColor="@color/white" android:textSize="20sp" diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index de53b92e0..5615c1307 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -152,6 +152,14 @@ 내용을 1자 이상 입력해주세요! 전송하기 + + 변경 할 닉네임을 입력하세요! + 한글 2~10 글자 사이\n영어 2~20 글자 사이\n공백 허용, 특수문자 사용 불가 + 닉네임 변경 + 변경 되었어요! + 변경을 실패 했어요! 다시 시도해주세요 + 변경 할 닉네임을 2글자 이상 작성해주세요! + 문제가 발생했어요. 다시 시도해주세요! diff --git a/android/domain/build.gradle b/android/domain/build.gradle index 4a7802e65..6b07e0b0c 100644 --- a/android/domain/build.gradle +++ b/android/domain/build.gradle @@ -20,4 +20,4 @@ tasks { test { useJUnitPlatform() } -} \ No newline at end of file +} diff --git a/android/domain/src/main/java/com/now/domain/repository/ProfileRepository.kt b/android/domain/src/main/java/com/now/domain/repository/ProfileRepository.kt new file mode 100644 index 000000000..d179c5df6 --- /dev/null +++ b/android/domain/src/main/java/com/now/domain/repository/ProfileRepository.kt @@ -0,0 +1,9 @@ +package com.now.domain.repository + +import com.now.domain.model.Player + +interface ProfileRepository { + suspend fun fetchProfile(): Player + + suspend fun modifyNickname(nickname: String): String +} diff --git a/backend/src/main/java/com/now/naaga/auth/infrastructure/jwt/AuthTokenGenerator.java b/backend/src/main/java/com/now/naaga/auth/infrastructure/jwt/AuthTokenGenerator.java index 52ec88d15..23062f740 100644 --- a/backend/src/main/java/com/now/naaga/auth/infrastructure/jwt/AuthTokenGenerator.java +++ b/backend/src/main/java/com/now/naaga/auth/infrastructure/jwt/AuthTokenGenerator.java @@ -14,8 +14,8 @@ @Component public class AuthTokenGenerator { - private static final long ACCESS_TOKEN_EXPIRE_TIME = 1000L * 60 * 60 * 24 * 30; // 30일 - private static final long REFRESH_TOKEN_EXPIRE_TIME = 1000L * 60 * 60 * 24 * 30; // 30일 + private static final long ACCESS_TOKEN_EXPIRE_TIME = 1000L * 20; // 20초 + private static final long REFRESH_TOKEN_EXPIRE_TIME = 1000L * 60 * 1; // 1분 private final JwtProvider jwtProvider; diff --git a/backend/src/main/java/com/now/naaga/letter/application/LetterService.java b/backend/src/main/java/com/now/naaga/letter/application/LetterService.java index f7e44998f..4f3814e92 100644 --- a/backend/src/main/java/com/now/naaga/letter/application/LetterService.java +++ b/backend/src/main/java/com/now/naaga/letter/application/LetterService.java @@ -28,7 +28,7 @@ @Service public class LetterService { - private static final double LETTER_RADIUS = 0.1; + private static final double LETTER_RADIUS = 0.05; private final LetterRepository letterRepository; diff --git a/backend/src/main/java/com/now/naaga/player/application/PlayerService.java b/backend/src/main/java/com/now/naaga/player/application/PlayerService.java index b3ea891ad..61e548f87 100644 --- a/backend/src/main/java/com/now/naaga/player/application/PlayerService.java +++ b/backend/src/main/java/com/now/naaga/player/application/PlayerService.java @@ -1,21 +1,24 @@ package com.now.naaga.player.application; -import static com.now.naaga.player.exception.PlayerExceptionType.PLAYER_NOT_FOUND; - +import com.now.naaga.member.domain.Member; import com.now.naaga.player.application.dto.AddScoreCommand; import com.now.naaga.player.application.dto.CreatePlayerCommand; import com.now.naaga.player.application.dto.DeletePlayerCommand; +import com.now.naaga.player.application.dto.EditPlayerNicknameCommand; import com.now.naaga.player.domain.Player; import com.now.naaga.player.domain.Rank; import com.now.naaga.player.exception.PlayerException; import com.now.naaga.player.persistence.repository.PlayerRepository; import com.now.naaga.player.presentation.dto.PlayerRequest; import com.now.naaga.score.domain.Score; -import java.util.ArrayList; -import java.util.List; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.ArrayList; +import java.util.List; + +import static com.now.naaga.player.exception.PlayerExceptionType.PLAYER_NOT_FOUND; + @Transactional @Service public class PlayerService { @@ -26,6 +29,14 @@ public PlayerService(final PlayerRepository playerRepository) { this.playerRepository = playerRepository; } + public Player editPlayerNickname(final EditPlayerNicknameCommand editPlayerNicknameCommand) { + final Long playerId = editPlayerNicknameCommand.playerId(); + final String newNickname = editPlayerNicknameCommand.nickname(); + final Player player = findPlayerById(playerId); + player.editNickname(newNickname); + return player; + } + @Transactional(readOnly = true) public Player findPlayerById(final Long id) { return playerRepository.findById(id) @@ -82,7 +93,9 @@ private int calculateTopPercent(final List players, } public Player create(final CreatePlayerCommand createPlayerCommand) { - final Player player = new Player(createPlayerCommand.nickname(), new Score(0), createPlayerCommand.member()); + final String nickname = createPlayerCommand.nickname(); + final Member member = createPlayerCommand.member(); + final Player player = Player.create(nickname, new Score(0), member); return playerRepository.save(player); } diff --git a/backend/src/main/java/com/now/naaga/player/application/dto/EditPlayerNicknameCommand.java b/backend/src/main/java/com/now/naaga/player/application/dto/EditPlayerNicknameCommand.java new file mode 100644 index 000000000..974b6682f --- /dev/null +++ b/backend/src/main/java/com/now/naaga/player/application/dto/EditPlayerNicknameCommand.java @@ -0,0 +1,16 @@ +package com.now.naaga.player.application.dto; + +import com.now.naaga.player.presentation.dto.EditPlayerRequest; +import com.now.naaga.player.presentation.dto.PlayerRequest; + +public record EditPlayerNicknameCommand(Long playerId, + String nickname) { + + public static EditPlayerNicknameCommand of(final PlayerRequest playerRequest, + final EditPlayerRequest editPlayerRequest) { + return new EditPlayerNicknameCommand( + playerRequest.playerId(), + editPlayerRequest.nickname() + ); + } +} diff --git a/backend/src/main/java/com/now/naaga/player/domain/Player.java b/backend/src/main/java/com/now/naaga/player/domain/Player.java index aaea7a4c3..2f1ecb45a 100644 --- a/backend/src/main/java/com/now/naaga/player/domain/Player.java +++ b/backend/src/main/java/com/now/naaga/player/domain/Player.java @@ -1,29 +1,32 @@ package com.now.naaga.player.domain; -import static java.lang.Boolean.FALSE; - import com.now.naaga.common.domain.BaseEntity; import com.now.naaga.member.domain.Member; +import com.now.naaga.player.exception.PlayerException; +import com.now.naaga.player.exception.PlayerExceptionType; import com.now.naaga.score.domain.Score; -import jakarta.persistence.AttributeOverride; -import jakarta.persistence.Column; -import jakarta.persistence.Embedded; -import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.OneToOne; -import java.util.Objects; +import jakarta.persistence.*; import org.hibernate.annotations.SQLDelete; import org.hibernate.annotations.Where; +import java.util.Objects; +import java.util.regex.Pattern; + +import static java.lang.Boolean.FALSE; + @SQLDelete(sql = "UPDATE player SET deleted = true WHERE id = ?") @Where(clause = "deleted = false") @Entity public class Player extends BaseEntity { + private static final int NICKNAME_MAX_SIZE = 20; + + private static final int NICKNAME_MIN_SIZE = 2; + + private static final Pattern NICKNAME_PATTERN = Pattern.compile("^.*[^가-힣a-zA-Z0-9\\s]+.*$"); + + private static final String UNAVAILABLE_REGEX = "[^가-힣a-zA-Z0-9\\s]+"; + @GeneratedValue(strategy = GenerationType.IDENTITY) @Id private Long id; @@ -50,7 +53,12 @@ public Player(final String nickname, this(null, nickname, totalScore, member, FALSE); } - public Player(final Long id, final String nickname, final Score totalScore, final Member member, final boolean deleted) { + public Player(final Long id, + final String nickname, + final Score totalScore, + final Member member, + final boolean deleted) { + validateNickname(nickname); this.id = id; this.nickname = nickname; this.totalScore = totalScore; @@ -58,6 +66,33 @@ public Player(final Long id, final String nickname, final Score totalScore, fina this.deleted = deleted; } + public static Player create(final String nickname, + final Score score, + final Member member) { + final String modifiedNickname = modifyToValidNickname(nickname); + return new Player(modifiedNickname, score, member); + } + + private static String modifyToValidNickname(final String nickname) { + final String modifiedNickname = nickname.replaceAll(UNAVAILABLE_REGEX, ""); + if (modifiedNickname.length() > 20) { + return modifiedNickname.substring(0, NICKNAME_MAX_SIZE); + } + return modifiedNickname; + } + + public void editNickname(final String newNickname) { + validateNickname(newNickname); + this.nickname = newNickname; + } + + private void validateNickname(final String nickname) { + final boolean isUnavailableNickname = NICKNAME_PATTERN.matcher(nickname).matches(); + if(isUnavailableNickname || nickname.length() < NICKNAME_MIN_SIZE || nickname.length() > NICKNAME_MAX_SIZE) { + throw new PlayerException(PlayerExceptionType.UNAVAILABLE_NICKNAME); + } + } + public void addScore(Score score) { this.totalScore = this.totalScore.plus(score); } diff --git a/backend/src/main/java/com/now/naaga/player/exception/PlayerExceptionType.java b/backend/src/main/java/com/now/naaga/player/exception/PlayerExceptionType.java index c894b6a0f..fed73e6ac 100644 --- a/backend/src/main/java/com/now/naaga/player/exception/PlayerExceptionType.java +++ b/backend/src/main/java/com/now/naaga/player/exception/PlayerExceptionType.java @@ -10,7 +10,12 @@ public enum PlayerExceptionType implements BaseExceptionType { HttpStatus.NOT_FOUND, "해당 플레이어는 존재하지 않습니다." ), - ; + + UNAVAILABLE_NICKNAME( + 306, + HttpStatus.BAD_REQUEST, + "올바르지 않은 닉네임" + ); private final int errorCode; private final HttpStatus httpStatus; diff --git a/backend/src/main/java/com/now/naaga/player/persistence/repository/PlayerRepository.java b/backend/src/main/java/com/now/naaga/player/persistence/repository/PlayerRepository.java index 305cc2fb4..8eb78ff7f 100644 --- a/backend/src/main/java/com/now/naaga/player/persistence/repository/PlayerRepository.java +++ b/backend/src/main/java/com/now/naaga/player/persistence/repository/PlayerRepository.java @@ -1,10 +1,11 @@ package com.now.naaga.player.persistence.repository; import com.now.naaga.player.domain.Player; -import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; +import java.util.List; + public interface PlayerRepository extends JpaRepository { List findByMemberId(final Long memberId); diff --git a/backend/src/main/java/com/now/naaga/player/presentation/PlayerController.java b/backend/src/main/java/com/now/naaga/player/presentation/PlayerController.java index 0638e5ac7..26ecbd34b 100644 --- a/backend/src/main/java/com/now/naaga/player/presentation/PlayerController.java +++ b/backend/src/main/java/com/now/naaga/player/presentation/PlayerController.java @@ -1,22 +1,22 @@ package com.now.naaga.player.presentation; -import static com.now.naaga.common.exception.CommonExceptionType.INVALID_REQUEST_PARAMETERS; - import com.now.naaga.auth.presentation.annotation.Auth; import com.now.naaga.common.exception.CommonException; import com.now.naaga.player.application.PlayerService; +import com.now.naaga.player.application.dto.EditPlayerNicknameCommand; +import com.now.naaga.player.domain.Player; import com.now.naaga.player.domain.Rank; -import com.now.naaga.player.presentation.dto.PlayerRequest; -import com.now.naaga.player.presentation.dto.RankResponse; +import com.now.naaga.player.presentation.dto.*; +import jakarta.validation.Valid; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + import java.util.List; import java.util.stream.Collectors; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; -@RequestMapping("/ranks") +import static com.now.naaga.common.exception.CommonExceptionType.INVALID_REQUEST_PARAMETERS; + @RestController public class PlayerController { @@ -26,14 +26,32 @@ public PlayerController(final PlayerService playerService) { this.playerService = playerService; } - @GetMapping("/my") + @PatchMapping("/profiles/my") + public ResponseEntity editPlayer(@Auth final PlayerRequest playerRequest, + @RequestBody @Valid final EditPlayerRequest editPlayerRequest) { + final EditPlayerNicknameCommand editPlayerNicknameCommand = EditPlayerNicknameCommand.of(playerRequest, editPlayerRequest); + final Player player = playerService.editPlayerNickname(editPlayerNicknameCommand); + final EditPlayerResponse editPlayerResponse = EditPlayerResponse.from(player); + return ResponseEntity + .status(HttpStatus.OK) + .body(editPlayerResponse); + } + + @GetMapping("/profiles/my") + public ResponseEntity findMyInfo(@Auth final PlayerRequest playerRequest) { + final Player player = playerService.findPlayerById(playerRequest.playerId()); + final PlayerResponse playerResponse = PlayerResponse.from(player); + return ResponseEntity.ok(playerResponse); + } + + @GetMapping("/ranks/my") public ResponseEntity findMyRank(@Auth final PlayerRequest playerRequest) { final Rank rank = playerService.getRankAndTopPercent(playerRequest); final RankResponse rankResponse = RankResponse.of(rank); return ResponseEntity.ok(rankResponse); } - @GetMapping + @GetMapping("/ranks") public ResponseEntity> findAllRank(@RequestParam(name = "sort-by") final String sortBy, @RequestParam(name = "order") final String order) { if (!sortBy.equalsIgnoreCase("RANK") || !order.equalsIgnoreCase("ASCENDING")) { @@ -42,9 +60,8 @@ public ResponseEntity> findAllRank(@RequestParam(name = "sort final List ranks = playerService.getAllPlayersByRanksAscending(); final List rankResponseList = ranks.stream() - .map(RankResponse::of) - .collect(Collectors.toList()); + .map(RankResponse::of) + .collect(Collectors.toList()); return ResponseEntity.ok(rankResponseList); } - } diff --git a/backend/src/main/java/com/now/naaga/player/presentation/dto/EditPlayerRequest.java b/backend/src/main/java/com/now/naaga/player/presentation/dto/EditPlayerRequest.java new file mode 100644 index 000000000..2aff4bebe --- /dev/null +++ b/backend/src/main/java/com/now/naaga/player/presentation/dto/EditPlayerRequest.java @@ -0,0 +1,7 @@ +package com.now.naaga.player.presentation.dto; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Pattern; + +public record EditPlayerRequest(@NotBlank @Pattern(regexp = "^[가-힣a-zA-Z0-9\\s]+$") String nickname) { +} diff --git a/backend/src/main/java/com/now/naaga/player/presentation/dto/EditPlayerResponse.java b/backend/src/main/java/com/now/naaga/player/presentation/dto/EditPlayerResponse.java new file mode 100644 index 000000000..cb3e8c467 --- /dev/null +++ b/backend/src/main/java/com/now/naaga/player/presentation/dto/EditPlayerResponse.java @@ -0,0 +1,10 @@ +package com.now.naaga.player.presentation.dto; + +import com.now.naaga.player.domain.Player; + +public record EditPlayerResponse(String nickname) { + + public static EditPlayerResponse from(final Player player) { + return new EditPlayerResponse(player.getNickname()); + } +} diff --git a/backend/src/test/java/com/now/naaga/NaagaApplicationTests.java b/backend/src/test/java/com/now/naaga/NaagaApplicationTests.java deleted file mode 100644 index 2b79106eb..000000000 --- a/backend/src/test/java/com/now/naaga/NaagaApplicationTests.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.now.naaga; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class NaagaApplicationTests { - - @Test - void contextLoads() { - } - -} diff --git a/backend/src/test/java/com/now/naaga/auth/application/AuthServiceTest.java b/backend/src/test/java/com/now/naaga/auth/application/AuthServiceTest.java index 106c8170e..b78214241 100644 --- a/backend/src/test/java/com/now/naaga/auth/application/AuthServiceTest.java +++ b/backend/src/test/java/com/now/naaga/auth/application/AuthServiceTest.java @@ -8,48 +8,24 @@ import com.now.naaga.auth.application.dto.AuthCommand; import com.now.naaga.auth.domain.AuthToken; -import com.now.naaga.auth.infrastructure.AuthClient; import com.now.naaga.auth.infrastructure.AuthType; import com.now.naaga.auth.infrastructure.dto.AuthInfo; import com.now.naaga.auth.infrastructure.dto.MemberAuth; -import com.now.naaga.common.builder.PlayerBuilder; +import com.now.naaga.common.ServiceTest; import com.now.naaga.member.domain.Member; -import com.now.naaga.member.persistence.repository.MemberRepository; import com.now.naaga.player.domain.Player; -import com.now.naaga.player.persistence.repository.PlayerRepository; import com.now.naaga.score.domain.Score; import java.util.Optional; import org.assertj.core.api.SoftAssertions; -import org.junit.jupiter.api.DisplayNameGeneration; -import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.test.context.jdbc.Sql; @SuppressWarnings("NonAsciiCharacters") -@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) -@Sql("/truncate.sql") -//@Transactional -@SpringBootTest -class AuthServiceTest { +class AuthServiceTest extends ServiceTest { @Autowired private AuthService authService; - @Autowired - private MemberRepository memberRepository; - - @Autowired - private PlayerRepository playerRepository; - - @Autowired - private PlayerBuilder playerBuilder; - - @MockBean - private AuthClient authClient; - @Test void 존재하지_않는_멤버는_저장_후_토큰을_발급한다() { // given @@ -74,7 +50,7 @@ class AuthServiceTest { void 존재하는_멤버는_저장_후_토큰을_발급한다() { // given final Player player = playerBuilder.init() - .build(); + .build(); final AuthCommand authCommand = new AuthCommand("1234", AuthType.KAKAO); when(authClient.requestOauthInfo(any())).thenReturn(AuthInfo.of(player.getMember().getEmail(), player.getNickname())); @@ -90,7 +66,7 @@ class AuthServiceTest { void 탈퇴한다() { // given final Player player = playerBuilder.init() - .build(); + .build(); final long authId = 1L; final MemberAuth memberAuth = new MemberAuth(player.getMember().getId(), authId, AuthType.KAKAO); doNothing().when(authClient).requestUnlink(authId); @@ -111,7 +87,7 @@ class AuthServiceTest { void 로그아웃한다() { // given final Player player = playerBuilder.init() - .build(); + .build(); final long authId = 1L; final MemberAuth memberAuth = new MemberAuth(player.getMember().getId(), authId, AuthType.KAKAO); doNothing().when(authClient).requestUnlink(authId); diff --git a/backend/src/test/java/com/now/naaga/auth/presentation/AuthControllerTest.java b/backend/src/test/java/com/now/naaga/auth/presentation/AuthControllerTest.java index eae1b861f..a8423b078 100644 --- a/backend/src/test/java/com/now/naaga/auth/presentation/AuthControllerTest.java +++ b/backend/src/test/java/com/now/naaga/auth/presentation/AuthControllerTest.java @@ -10,19 +10,14 @@ import static org.mockito.Mockito.when; import com.now.naaga.auth.domain.AuthToken; -import com.now.naaga.auth.infrastructure.AuthClient; import com.now.naaga.auth.infrastructure.AuthType; import com.now.naaga.auth.infrastructure.MemberAuthMapper; import com.now.naaga.auth.infrastructure.dto.AuthInfo; import com.now.naaga.auth.infrastructure.dto.MemberAuth; -import com.now.naaga.auth.infrastructure.jwt.AuthTokenGenerator; -import com.now.naaga.auth.infrastructure.jwt.JwtProvider; -import com.now.naaga.auth.persistence.AuthRepository; import com.now.naaga.auth.presentation.dto.AuthRequest; import com.now.naaga.auth.presentation.dto.AuthResponse; import com.now.naaga.auth.presentation.dto.RefreshTokenRequest; -import com.now.naaga.common.CommonControllerTest; -import com.now.naaga.common.builder.PlayerBuilder; +import com.now.naaga.common.ControllerTest; import com.now.naaga.common.exception.ExceptionResponse; import com.now.naaga.member.domain.Member; import com.now.naaga.player.domain.Player; @@ -31,38 +26,12 @@ import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; import java.util.Date; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayNameGeneration; -import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; @SuppressWarnings("NonAsciiCharacters") -@DisplayNameGeneration(ReplaceUnderscores.class) -class AuthControllerTest extends CommonControllerTest { - - @Autowired - private JwtProvider jwtProvider; - - @Autowired - private AuthTokenGenerator authTokenGenerator; - - @Autowired - private AuthRepository authRepository; - - @MockBean - private AuthClient authClient; - - @Autowired - private PlayerBuilder playerBuilder; - - @BeforeEach - protected void setUp() { - super.setUp(); - } +class AuthControllerTest extends ControllerTest { @Test void 이미_존재하는_멤버_정보로_카카오_토큰을_통해서_로그인_요청을_하면_액세스_토큰을_발급한다() { @@ -129,11 +98,11 @@ protected void setUp() { void 유효한_리프레시_토큰으로_만료된_액세스_토큰_발급_요청을_보낸_경우_새로_발급한_액세스_토큰과_리프레시_토큰을_반환한다() { // given final Player player = playerBuilder.init() - .build(); + .build(); final long now = (new Date()).getTime(); - final Date accessTokenExpiredAt = new Date(now -1); - final Date refreshTokenExpiredAt = new Date(now + 360000*24); + final Date accessTokenExpiredAt = new Date(now - 1); + final Date refreshTokenExpiredAt = new Date(now + 360000 * 24); final MemberAuth memberAuth = new MemberAuth(player.getMember().getId(), 1L, AuthType.KAKAO); final String convertedString = MemberAuthMapper.convertMemberAuthToString(memberAuth); final String expiredAccessToken = jwtProvider.generate(convertedString, accessTokenExpiredAt); @@ -143,14 +112,14 @@ protected void setUp() { //when final ExtractableResponse extract = RestAssured.given() - .log().all() - .contentType(MediaType.APPLICATION_JSON_VALUE) - .body(new RefreshTokenRequest(validRefreshToken)) - .when() - .post("/auth/refresh") - .then() - .log().all() - .extract(); + .log().all() + .contentType(MediaType.APPLICATION_JSON_VALUE) + .body(new RefreshTokenRequest(validRefreshToken)) + .when() + .post("/auth/refresh") + .then() + .log().all() + .extract(); //then final int actualStatusCode = extract.statusCode(); @@ -167,11 +136,11 @@ protected void setUp() { void 유효한_리프레시_토큰으로_만료되지_않은_액세스_토큰_발급_요청을_보낸_경우_리프레시_토큰을_폐기하고_예외를_발생한다() { // given final Player player = playerBuilder.init() - .build(); + .build(); final long now = (new Date()).getTime(); - final Date accessTokenExpiredAt = new Date(now + 360000*24); - final Date refreshTokenExpiredAt = new Date(now + 360000*24); + final Date accessTokenExpiredAt = new Date(now + 360000 * 24); + final Date refreshTokenExpiredAt = new Date(now + 360000 * 24); final MemberAuth memberAuth = new MemberAuth(player.getMember().getId(), 1L, AuthType.KAKAO); final String convertedString = MemberAuthMapper.convertMemberAuthToString(memberAuth); final String validAccessToken = jwtProvider.generate(convertedString, accessTokenExpiredAt); @@ -181,27 +150,27 @@ protected void setUp() { //when final ExtractableResponse extract = RestAssured.given() - .log().all() - .contentType(MediaType.APPLICATION_JSON_VALUE) - .body(new RefreshTokenRequest(validRefreshToken)) - .when() - .post("/auth/refresh") - .then() - .log().all() - .extract(); + .log().all() + .contentType(MediaType.APPLICATION_JSON_VALUE) + .body(new RefreshTokenRequest(validRefreshToken)) + .when() + .post("/auth/refresh") + .then() + .log().all() + .extract(); //then final int actualStatusCode = extract.statusCode(); final int expectedStatusCode = HttpStatus.UNAUTHORIZED.value(); final ExceptionResponse actualResponse = extract.body().as(ExceptionResponse.class); final ExceptionResponse expectedResponse = new ExceptionResponse(INVALID_TOKEN_ACCESS.errorCode(), - INVALID_TOKEN_ACCESS.errorMessage()); + INVALID_TOKEN_ACCESS.errorMessage()); assertSoftly(softly -> { softly.assertThat(actualStatusCode).isEqualTo(expectedStatusCode); softly.assertThat(actualResponse) - .usingRecursiveComparison() - .isEqualTo(expectedResponse); + .usingRecursiveComparison() + .isEqualTo(expectedResponse); }); } @@ -209,10 +178,10 @@ protected void setUp() { void 리프레시_토큰이_만료된_경우_리프레시_토큰을_폐기하고_예외를_발생한다() { // given final Player player = playerBuilder.init() - .build(); + .build(); final long now = (new Date()).getTime(); - final Date accessTokenExpiredAt = new Date(now -1 ); + final Date accessTokenExpiredAt = new Date(now - 1); final Date refreshTokenExpiredAt = new Date(now - 1); final String expiredAccessToken = jwtProvider.generate(player.getMember().getId().toString(), accessTokenExpiredAt); final String expiredRefreshToken = jwtProvider.generate(player.getMember().getId().toString(), refreshTokenExpiredAt); @@ -221,27 +190,27 @@ protected void setUp() { //when final ExtractableResponse extract = RestAssured.given() - .log().all() - .contentType(MediaType.APPLICATION_JSON_VALUE) - .body(new RefreshTokenRequest(expiredRefreshToken)) - .when() - .post("/auth/refresh") - .then() - .log().all() - .extract(); + .log().all() + .contentType(MediaType.APPLICATION_JSON_VALUE) + .body(new RefreshTokenRequest(expiredRefreshToken)) + .when() + .post("/auth/refresh") + .then() + .log().all() + .extract(); //then final int actualStatusCode = extract.statusCode(); final int expectedStatusCode = HttpStatus.UNAUTHORIZED.value(); final ExceptionResponse actualResponse = extract.body().as(ExceptionResponse.class); final ExceptionResponse expectedResponse = new ExceptionResponse(EXPIRED_TOKEN.errorCode(), - EXPIRED_TOKEN.errorMessage()); + EXPIRED_TOKEN.errorMessage()); assertSoftly(softly -> { softly.assertThat(actualStatusCode).isEqualTo(expectedStatusCode); softly.assertThat(actualResponse) - .usingRecursiveComparison() - .isEqualTo(expectedResponse); + .usingRecursiveComparison() + .isEqualTo(expectedResponse); }); } @@ -249,27 +218,27 @@ protected void setUp() { void 유효하지_않은_리프레시_토큰인_경우_예외를_발생한다() { //given & when final ExtractableResponse extract = RestAssured.given() - .log().all() - .contentType(MediaType.APPLICATION_JSON_VALUE) - .body(new RefreshTokenRequest("이상한 문자열")) - .when() - .post("/auth/refresh") - .then() - .log().all() - .extract(); + .log().all() + .contentType(MediaType.APPLICATION_JSON_VALUE) + .body(new RefreshTokenRequest("이상한 문자열")) + .when() + .post("/auth/refresh") + .then() + .log().all() + .extract(); //then final int actualStatusCode = extract.statusCode(); final int expectedStatusCode = HttpStatus.UNAUTHORIZED.value(); final ExceptionResponse actualResponse = extract.body().as(ExceptionResponse.class); final ExceptionResponse expectedResponse = new ExceptionResponse(INVALID_TOKEN.errorCode(), - INVALID_TOKEN.errorMessage()); + INVALID_TOKEN.errorMessage()); assertSoftly(softly -> { softly.assertThat(actualStatusCode).isEqualTo(expectedStatusCode); softly.assertThat(actualResponse) - .usingRecursiveComparison() - .isEqualTo(expectedResponse); + .usingRecursiveComparison() + .isEqualTo(expectedResponse); }); } @@ -277,20 +246,20 @@ protected void setUp() { void 액세스_토큰을_받아_회원_탈퇴를_진행한다() { // given final Player player = playerBuilder.init() - .build(); + .build(); final AuthToken authToken = authTokenGenerator.generate(player.getMember(), 1L, AuthType.KAKAO); authRepository.save(authToken); doNothing().when(authClient).requestUnlink(any()); // when final ExtractableResponse extract = RestAssured.given() - .log().all() - .header("Authorization", "Bearer " + authToken.getAccessToken()) - .when() - .delete("/auth/unlink") - .then() - .log().all() - .extract(); + .log().all() + .header("Authorization", "Bearer " + authToken.getAccessToken()) + .when() + .delete("/auth/unlink") + .then() + .log().all() + .extract(); // then final int actualStatusCode = extract.statusCode(); @@ -303,20 +272,20 @@ protected void setUp() { void 액세스_토큰을_받아_로그아웃을_진행한다() { // given final Player player = playerBuilder.init() - .build(); + .build(); final AuthToken authToken = authTokenGenerator.generate(player.getMember(), 1L, AuthType.KAKAO); authRepository.save(authToken); doNothing().when(authClient).requestLogout(any()); // when final ExtractableResponse extract = RestAssured.given() - .log().all() - .header("Authorization", "Bearer " + authToken.getAccessToken()) - .when() - .delete("/auth") - .then() - .log().all() - .extract(); + .log().all() + .header("Authorization", "Bearer " + authToken.getAccessToken()) + .when() + .delete("/auth") + .then() + .log().all() + .extract(); // then final int actualStatusCode = extract.statusCode(); diff --git a/backend/src/test/java/com/now/naaga/auth/presentation/AuthInterceptorTest.java b/backend/src/test/java/com/now/naaga/auth/presentation/AuthInterceptorTest.java index ae30a54fe..652553ff3 100644 --- a/backend/src/test/java/com/now/naaga/auth/presentation/AuthInterceptorTest.java +++ b/backend/src/test/java/com/now/naaga/auth/presentation/AuthInterceptorTest.java @@ -8,15 +8,10 @@ import com.now.naaga.auth.domain.AuthToken; import com.now.naaga.auth.infrastructure.AuthType; -import com.now.naaga.auth.infrastructure.jwt.AuthTokenGenerator; -import com.now.naaga.auth.infrastructure.jwt.JwtProvider; -import com.now.naaga.common.CommonControllerTest; -import com.now.naaga.common.builder.PlayerBuilder; +import com.now.naaga.common.ControllerTest; import com.now.naaga.common.exception.ExceptionResponse; import com.now.naaga.member.domain.Member; -import com.now.naaga.member.persistence.repository.MemberRepository; import com.now.naaga.player.domain.Player; -import com.now.naaga.player.persistence.repository.PlayerRepository; import io.restassured.RestAssured; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; @@ -24,32 +19,10 @@ import org.junit.jupiter.api.DisplayNameGeneration; import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; @SuppressWarnings("NonAsciiCharacters") -@DisplayNameGeneration(ReplaceUnderscores.class) -public class AuthInterceptorTest extends CommonControllerTest { - - @Autowired - private MemberRepository memberRepository; - - @Autowired - private PlayerRepository playerRepository; - - @Autowired - private AuthTokenGenerator authTokenGenerator; - - @Autowired - private JwtProvider jwtProvider; - - @Autowired - private PlayerBuilder playerBuilder; - - @BeforeEach - protected void setUp() { - super.setUp(); - } +public class AuthInterceptorTest extends ControllerTest { @Test void 인증_헤더_정보가_존재하지_않을_때_401_응답한다() { @@ -136,7 +109,7 @@ protected void setUp() { void 인증_헤더의_토큰_정보가_존재하지_않는_멤버일_때_401_응답한다() { // given final Player player = playerBuilder.init() - .build(); + .build(); final AuthToken generate = authTokenGenerator.generate(player.getMember(), 1L, AuthType.KAKAO); final String accessToken = generate.getAccessToken(); @@ -168,7 +141,7 @@ protected void setUp() { void 인증_헤더의_토큰_정보가_존재하는_멤버일_때_정상응답한다() { // given final Player player = playerBuilder.init() - .build(); + .build(); final AuthToken authToken = authTokenGenerator.generate(player.getMember(), 1L, AuthType.KAKAO); final String accessToken = authToken.getAccessToken(); diff --git a/backend/src/test/java/com/now/naaga/auth/presentation/PlayerArgumentResolverTest.java b/backend/src/test/java/com/now/naaga/auth/presentation/PlayerArgumentResolverTest.java index 702334f78..446cd6dba 100644 --- a/backend/src/test/java/com/now/naaga/auth/presentation/PlayerArgumentResolverTest.java +++ b/backend/src/test/java/com/now/naaga/auth/presentation/PlayerArgumentResolverTest.java @@ -6,39 +6,17 @@ import com.now.naaga.auth.domain.AuthToken; import com.now.naaga.auth.infrastructure.AuthType; -import com.now.naaga.auth.infrastructure.jwt.AuthTokenGenerator; -import com.now.naaga.common.CommonControllerTest; -import com.now.naaga.common.builder.PlayerBuilder; +import com.now.naaga.common.ControllerTest; import com.now.naaga.common.exception.ExceptionResponse; import com.now.naaga.player.domain.Player; -import com.now.naaga.player.persistence.repository.PlayerRepository; import io.restassured.RestAssured; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayNameGeneration; -import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; @SuppressWarnings("NonAsciiCharacters") -@DisplayNameGeneration(ReplaceUnderscores.class) -public class PlayerArgumentResolverTest extends CommonControllerTest { - - @Autowired - private PlayerRepository playerRepository; - - @Autowired - private AuthTokenGenerator authTokenGenerator; - - @Autowired - private PlayerBuilder playerBuilder; - - @BeforeEach - protected void setUp() { - super.setUp(); - } +public class PlayerArgumentResolverTest extends ControllerTest { @Test void 인증_헤더의_토큰_정보가_존재하지_않는_멤버일_때_예외를_발생한다() { diff --git a/backend/src/test/java/com/now/naaga/auth/presentation/interceptor/ManagerAuthInterceptorTest.java b/backend/src/test/java/com/now/naaga/auth/presentation/interceptor/ManagerAuthInterceptorTest.java index 6eb262c4d..d121b7969 100644 --- a/backend/src/test/java/com/now/naaga/auth/presentation/interceptor/ManagerAuthInterceptorTest.java +++ b/backend/src/test/java/com/now/naaga/auth/presentation/interceptor/ManagerAuthInterceptorTest.java @@ -4,24 +4,18 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import com.now.naaga.auth.exception.AuthException; +import com.now.naaga.common.ControllerTest; import java.util.Base64; -import org.junit.jupiter.api.DisplayNameGeneration; -import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Test; import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.test.context.SpringBootTest; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; -import org.springframework.test.context.ActiveProfiles; import org.springframework.web.servlet.mvc.Controller; -@ActiveProfiles("test") @SuppressWarnings("NonAsciiCharacters") -@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) -@SpringBootTest -class ManagerAuthInterceptorTest { +class ManagerAuthInterceptorTest extends ControllerTest { @Value("${manager.id}") String id; diff --git a/backend/src/test/java/com/now/naaga/common/AbstractTest.java b/backend/src/test/java/com/now/naaga/common/AbstractTest.java new file mode 100644 index 000000000..19f744c35 --- /dev/null +++ b/backend/src/test/java/com/now/naaga/common/AbstractTest.java @@ -0,0 +1,124 @@ +package com.now.naaga.common; + +import com.now.naaga.auth.infrastructure.AuthClient; +import com.now.naaga.auth.persistence.AuthRepository; +import com.now.naaga.common.builder.GameBuilder; +import com.now.naaga.common.builder.GameResultBuilder; +import com.now.naaga.common.builder.LetterBuilder; +import com.now.naaga.common.builder.MemberBuilder; +import com.now.naaga.common.builder.PlaceBuilder; +import com.now.naaga.common.builder.PlaceLikeBuilder; +import com.now.naaga.common.builder.PlaceStatisticsBuilder; +import com.now.naaga.common.builder.PlayerBuilder; +import com.now.naaga.common.builder.ReadLetterLogBuilder; +import com.now.naaga.common.builder.TemporaryPlaceBuilder; +import com.now.naaga.common.builder.WriteLetterLogBuilder; +import com.now.naaga.common.infrastructure.AwsS3FileManager; +import com.now.naaga.game.repository.GameRepository; +import com.now.naaga.game.repository.HintRepository; +import com.now.naaga.gameresult.repository.GameResultRepository; +import com.now.naaga.letter.repository.LetterRepository; +import com.now.naaga.letter.repository.letterlog.ReadLetterLogRepository; +import com.now.naaga.letter.repository.letterlog.WriteLetterLogRepository; +import com.now.naaga.like.repository.PlaceLikeRepository; +import com.now.naaga.member.persistence.repository.MemberRepository; +import com.now.naaga.place.repository.PlaceRepository; +import com.now.naaga.place.repository.PlaceStatisticsRepository; +import com.now.naaga.player.persistence.repository.PlayerRepository; +import com.now.naaga.temporaryplace.repository.TemporaryPlaceRepository; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.jdbc.Sql; + +@DisplayNameGeneration(ReplaceUnderscores.class) +@Sql("/truncate.sql") +@ActiveProfiles("test") +public abstract class AbstractTest { + + /*------------------------------------------------------------------*/ + + @Autowired + protected MemberBuilder memberBuilder; + + @Autowired + protected PlayerBuilder playerBuilder; + + @Autowired + protected PlaceBuilder placeBuilder; + + @Autowired + protected GameBuilder gameBuilder; + + @Autowired + protected GameResultBuilder gameResultBuilder; + + @Autowired + protected PlaceStatisticsBuilder placeStatisticsBuilder; + + @Autowired + protected TemporaryPlaceBuilder temporaryPlaceBuilder; + + @Autowired + protected PlaceLikeBuilder placeLikeBuilder; + + @Autowired + protected LetterBuilder letterBuilder; + + @Autowired + protected ReadLetterLogBuilder readLetterLogBuilder; + + @Autowired + protected WriteLetterLogBuilder writeLetterLogBuilder; + + /*------------------------------------------------------------------*/ + + @Autowired + protected AuthRepository authRepository; + + @Autowired + protected MemberRepository memberRepository; + + @Autowired + protected PlayerRepository playerRepository; + + @Autowired + protected PlaceRepository placeRepository; + + @Autowired + protected GameRepository gameRepository; + + @Autowired + protected HintRepository hintRepository; + + @Autowired + protected GameResultRepository gameResultRepository; + + @Autowired + protected PlaceStatisticsRepository placeStatisticsRepository; + + @Autowired + protected TemporaryPlaceRepository temporaryPlaceRepository; + + @Autowired + protected PlaceLikeRepository placeLikeRepository; + + @Autowired + protected LetterRepository letterRepository; + + @Autowired + protected ReadLetterLogRepository readLetterLogRepository; + + @Autowired + protected WriteLetterLogRepository writeLetterLogRepository; + + /*------------------------------------------------------------------*/ + + @MockBean + protected AuthClient authClient; + + @MockBean + protected AwsS3FileManager awsS3FileManager; +} diff --git a/backend/src/test/java/com/now/naaga/common/CommonControllerTest.java b/backend/src/test/java/com/now/naaga/common/CommonControllerTest.java deleted file mode 100644 index fb1103278..000000000 --- a/backend/src/test/java/com/now/naaga/common/CommonControllerTest.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.now.naaga.common; - -import io.restassured.RestAssured; -import io.restassured.response.ExtractableResponse; -import io.restassured.response.Response; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.test.web.server.LocalServerPort; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.jdbc.Sql; - -@ActiveProfiles("test") -@Sql("/truncate.sql") -@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) -public abstract class CommonControllerTest { - - @LocalServerPort - private int port; - - protected void setUp() { - RestAssured.port = port; - } - - protected Long getIdFromLocationHeader(ExtractableResponse extractableResponse) { - String[] split = extractableResponse.header("Location").split("/"); - return Long.parseLong(split[split.length - 1]); - } -} diff --git a/backend/src/test/java/com/now/naaga/common/ControllerTest.java b/backend/src/test/java/com/now/naaga/common/ControllerTest.java new file mode 100644 index 000000000..1427c6519 --- /dev/null +++ b/backend/src/test/java/com/now/naaga/common/ControllerTest.java @@ -0,0 +1,52 @@ +package com.now.naaga.common; + +import com.now.naaga.auth.domain.AuthToken; +import com.now.naaga.auth.infrastructure.AuthType; +import com.now.naaga.auth.infrastructure.jwt.AuthTokenGenerator; +import com.now.naaga.auth.infrastructure.jwt.JwtProvider; +import com.now.naaga.member.domain.Member; +import com.now.naaga.player.domain.Player; +import io.restassured.RestAssured; +import io.restassured.response.ExtractableResponse; +import io.restassured.response.Response; +import org.junit.jupiter.api.BeforeEach; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.boot.test.web.server.LocalServerPort; + +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) +public abstract class ControllerTest extends AbstractTest { + + @Autowired + protected AuthTokenGenerator authTokenGenerator; + + @Autowired + protected JwtProvider jwtProvider; + + @LocalServerPort + private int port; + + @BeforeEach + void setUp() { + RestAssured.port = port; + } + + protected String authorizationForBearer(final Player player) { + final Member member = player.getMember(); + final AuthToken generate = authTokenGenerator.generate(member, member.getId(), AuthType.KAKAO); + final String accessToken = generate.getAccessToken(); + return "Bearer " + accessToken; + } + + protected String authorizationForBearer(final Member member) { + final AuthToken generate = authTokenGenerator.generate(member, member.getId(), AuthType.KAKAO); + final String accessToken = generate.getAccessToken(); + return "Bearer " + accessToken; + } + + protected Long getIdFromLocationHeader(ExtractableResponse extractableResponse) { + String[] split = extractableResponse.header("Location").split("/"); + return Long.parseLong(split[split.length - 1]); + } +} diff --git a/backend/src/test/java/com/now/naaga/common/ServiceTest.java b/backend/src/test/java/com/now/naaga/common/ServiceTest.java new file mode 100644 index 000000000..9c295a170 --- /dev/null +++ b/backend/src/test/java/com/now/naaga/common/ServiceTest.java @@ -0,0 +1,8 @@ +package com.now.naaga.common; + +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +public abstract class ServiceTest extends AbstractTest { + +} diff --git a/backend/src/test/java/com/now/naaga/common/fixture/PlayerFixture.java b/backend/src/test/java/com/now/naaga/common/fixture/PlayerFixture.java index 6645b3387..7bfaa4e92 100644 --- a/backend/src/test/java/com/now/naaga/common/fixture/PlayerFixture.java +++ b/backend/src/test/java/com/now/naaga/common/fixture/PlayerFixture.java @@ -7,7 +7,7 @@ public class PlayerFixture { - public static final String NICKNAME = "player_nickname"; + public static final String NICKNAME = "player nickname"; public static final Score SCORE = new Score(0); diff --git a/backend/src/test/java/com/now/naaga/game/application/GameServiceTest.java b/backend/src/test/java/com/now/naaga/game/application/GameServiceTest.java index a0708d37e..bad450eda 100644 --- a/backend/src/test/java/com/now/naaga/game/application/GameServiceTest.java +++ b/backend/src/test/java/com/now/naaga/game/application/GameServiceTest.java @@ -1,9 +1,24 @@ package com.now.naaga.game.application; -import com.now.naaga.common.builder.GameBuilder; -import com.now.naaga.common.builder.GameResultBuilder; -import com.now.naaga.common.builder.PlaceBuilder; -import com.now.naaga.common.builder.PlayerBuilder; +import static com.now.naaga.common.fixture.PositionFixture.역삼역_좌표; +import static com.now.naaga.common.fixture.PositionFixture.잠실_루터회관_정문_좌표; +import static com.now.naaga.common.fixture.PositionFixture.잠실역_교보문고_좌표; +import static com.now.naaga.common.fixture.PositionFixture.장미_상가; +import static com.now.naaga.game.domain.EndType.ARRIVED; +import static com.now.naaga.game.domain.EndType.GIVE_UP; +import static com.now.naaga.game.domain.GameStatus.DONE; +import static com.now.naaga.game.domain.GameStatus.IN_PROGRESS; +import static com.now.naaga.game.exception.GameExceptionType.ALREADY_IN_PROGRESS; +import static com.now.naaga.game.exception.GameExceptionType.CAN_NOT_FIND_PLACE; +import static com.now.naaga.game.exception.GameExceptionType.INACCESSIBLE_AUTHENTICATION; +import static com.now.naaga.gameresult.domain.ResultType.FAIL; +import static com.now.naaga.gameresult.domain.ResultType.SUCCESS; +import static com.now.naaga.gameresult.exception.GameResultExceptionType.GAME_RESULT_NOT_EXIST; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.SoftAssertions.assertSoftly; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import com.now.naaga.common.ServiceTest; import com.now.naaga.game.application.dto.CreateGameCommand; import com.now.naaga.game.application.dto.EndGameCommand; import com.now.naaga.game.application.dto.FindGameByIdCommand; @@ -18,70 +33,38 @@ import com.now.naaga.place.domain.Place; import com.now.naaga.player.domain.Player; import com.now.naaga.player.presentation.dto.PlayerRequest; -import org.junit.jupiter.api.DisplayNameGeneration; -import org.junit.jupiter.api.DisplayNameGenerator; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.jdbc.Sql; - import java.time.LocalDateTime; import java.time.Month; import java.util.List; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; -import static com.now.naaga.common.fixture.PositionFixture.*; -import static com.now.naaga.game.domain.EndType.ARRIVED; -import static com.now.naaga.game.domain.EndType.GIVE_UP; -import static com.now.naaga.game.domain.GameStatus.DONE; -import static com.now.naaga.game.domain.GameStatus.IN_PROGRESS; -import static com.now.naaga.game.exception.GameExceptionType.*; -import static com.now.naaga.gameresult.domain.ResultType.FAIL; -import static com.now.naaga.gameresult.domain.ResultType.SUCCESS; -import static com.now.naaga.gameresult.exception.GameResultExceptionType.GAME_RESULT_NOT_EXIST; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.SoftAssertions.assertSoftly; -import static org.junit.jupiter.api.Assertions.assertThrows; - -@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) -@Sql("/truncate.sql") -@SpringBootTest -class GameServiceTest { +@SuppressWarnings("NonAsciiCharacters") +class GameServiceTest extends ServiceTest { @Autowired private GameService gameService; - @Autowired - private GameBuilder gameBuilder; - - @Autowired - private GameResultBuilder gameResultBuilder; - - @Autowired - private PlayerBuilder playerBuilder; - - @Autowired - private PlaceBuilder placeBuilder; - @Test void 게임_id로_게임_결과를_조회한다() { // given final Player player = playerBuilder.init() - .build(); + .build(); final Place destination = placeBuilder.init() - .position(잠실_루터회관_정문_좌표) - .build(); + .position(잠실_루터회관_정문_좌표) + .build(); final Game game = gameBuilder.init() - .place(destination) - .player(player) - .startPosition(잠실역_교보문고_좌표) - .build(); + .place(destination) + .player(player) + .startPosition(잠실역_교보문고_좌표) + .build(); final GameResult gameResult = gameResultBuilder.init() - .resultType(SUCCESS) - .game(game) - .build(); + .resultType(SUCCESS) + .game(game) + .build(); // when final Long actual = gameService.findGameResultByGameId(game.getId()).getId(); @@ -94,17 +77,17 @@ class GameServiceTest { void 게임_id로_게임_결과를_조회할때_존재하지_않으면_예외를_발생시킨다() { // given & when final Player player = playerBuilder.init() - .build(); + .build(); final Place destination = placeBuilder.init() - .position(잠실_루터회관_정문_좌표) - .build(); + .position(잠실_루터회관_정문_좌표) + .build(); final Game game = gameBuilder.init() - .place(destination) - .player(player) - .startPosition(잠실역_교보문고_좌표) - .build(); + .place(destination) + .player(player) + .startPosition(잠실역_교보문고_좌표) + .build(); //then GameResultException gameResultException = assertThrows(GameResultException.class, () -> gameService.findGameResultByGameId(game.getId())); @@ -115,48 +98,48 @@ class GameServiceTest { void 플레이어의_모든_게임결과를_생성순서로_정렬하여_조회한다() { // given final Player player = playerBuilder.init() - .build(); + .build(); final Place destination = placeBuilder.init() - .position(잠실_루터회관_정문_좌표) - .build(); + .position(잠실_루터회관_정문_좌표) + .build(); final Game game1 = gameBuilder.init() - .place(destination) - .player(player) - .startTime(LocalDateTime.of(2023, Month.AUGUST, 13, 15, 30, 0)) - .endTime(LocalDateTime.of(2023, Month.AUGUST, 13, 17, 30, 0)) - .gameStatus(DONE) - .startPosition(잠실역_교보문고_좌표) - .build(); + .place(destination) + .player(player) + .startTime(LocalDateTime.of(2023, Month.AUGUST, 13, 15, 30, 0)) + .endTime(LocalDateTime.of(2023, Month.AUGUST, 13, 17, 30, 0)) + .gameStatus(DONE) + .startPosition(잠실역_교보문고_좌표) + .build(); final Game game2 = gameBuilder.init() - .place(destination) - .player(player) - .startTime(LocalDateTime.of(2023, Month.AUGUST, 12, 15, 30, 0)) - .endTime(LocalDateTime.of(2023, Month.AUGUST, 12, 17, 30, 0)) - .gameStatus(DONE) - .startPosition(잠실역_교보문고_좌표) - .build(); + .place(destination) + .player(player) + .startTime(LocalDateTime.of(2023, Month.AUGUST, 12, 15, 30, 0)) + .endTime(LocalDateTime.of(2023, Month.AUGUST, 12, 17, 30, 0)) + .gameStatus(DONE) + .startPosition(잠실역_교보문고_좌표) + .build(); final Game game3 = gameBuilder.init() - .place(destination) - .player(player) - .startTime(LocalDateTime.of(2023, Month.AUGUST, 12, 15, 30, 0)) - .endTime(null) - .gameStatus(IN_PROGRESS) - .startPosition(잠실역_교보문고_좌표) - .build(); + .place(destination) + .player(player) + .startTime(LocalDateTime.of(2023, Month.AUGUST, 12, 15, 30, 0)) + .endTime(null) + .gameStatus(IN_PROGRESS) + .startPosition(잠실역_교보문고_좌표) + .build(); final GameResult gameResult1 = gameResultBuilder.init() - .resultType(SUCCESS) - .game(game1) - .build(); + .resultType(SUCCESS) + .game(game1) + .build(); final GameResult gameResult2 = gameResultBuilder.init() - .resultType(FAIL) - .game(game2) - .build(); + .resultType(FAIL) + .game(game2) + .build(); //when final List expected = gameService.findAllGameResult(new PlayerRequest(player.getId())); @@ -173,20 +156,20 @@ class GameServiceTest { void 플레이어의_게임_결과가_없으면_빈리스트를_반환한다() { // given final Player player = playerBuilder.init() - .build(); + .build(); final Place destination = placeBuilder.init() - .position(잠실_루터회관_정문_좌표) - .build(); + .position(잠실_루터회관_정문_좌표) + .build(); final Game game = gameBuilder.init() - .place(destination) - .player(player) - .startTime(LocalDateTime.of(2023, Month.AUGUST, 12, 15, 30, 0)) - .endTime(null) - .gameStatus(IN_PROGRESS) - .startPosition(잠실역_교보문고_좌표) - .build(); + .place(destination) + .player(player) + .startTime(LocalDateTime.of(2023, Month.AUGUST, 12, 15, 30, 0)) + .endTime(null) + .gameStatus(IN_PROGRESS) + .startPosition(잠실역_교보문고_좌표) + .build(); //when final List expected = gameService.findAllGameResult(new PlayerRequest(player.getId())); @@ -199,39 +182,39 @@ class GameServiceTest { void 플레이어의_통계를_조회한다() { // given final Player player = playerBuilder.init() - .build(); + .build(); final Place destination = placeBuilder.init() - .position(잠실_루터회관_정문_좌표) - .build(); + .position(잠실_루터회관_정문_좌표) + .build(); final Game game1 = gameBuilder.init() - .place(destination) - .player(player) - .gameStatus(DONE) - .startTime(LocalDateTime.of(2023, Month.AUGUST, 13, 15, 30, 0)) - .endTime(LocalDateTime.of(2023, Month.AUGUST, 13, 17, 30, 0)) - .startPosition(잠실역_교보문고_좌표) - .build(); + .place(destination) + .player(player) + .gameStatus(DONE) + .startTime(LocalDateTime.of(2023, Month.AUGUST, 13, 15, 30, 0)) + .endTime(LocalDateTime.of(2023, Month.AUGUST, 13, 17, 30, 0)) + .startPosition(잠실역_교보문고_좌표) + .build(); final Game game2 = gameBuilder.init() - .place(destination) - .player(player) - .gameStatus(DONE) - .startTime(LocalDateTime.of(2023, Month.AUGUST, 12, 15, 30, 0)) - .endTime(LocalDateTime.of(2023, Month.AUGUST, 12, 17, 30, 0)) - .startPosition(잠실역_교보문고_좌표) - .build(); + .place(destination) + .player(player) + .gameStatus(DONE) + .startTime(LocalDateTime.of(2023, Month.AUGUST, 12, 15, 30, 0)) + .endTime(LocalDateTime.of(2023, Month.AUGUST, 12, 17, 30, 0)) + .startPosition(잠실역_교보문고_좌표) + .build(); final GameResult gameResult1 = gameResultBuilder.init() - .resultType(SUCCESS) - .game(game1) - .build(); + .resultType(SUCCESS) + .game(game1) + .build(); final GameResult gameResult2 = gameResultBuilder.init() - .resultType(FAIL) - .game(game2) - .build(); + .resultType(FAIL) + .game(game2) + .build(); final int expectedTotalDistance = (int) 잠실_루터회관_정문_좌표.calculateDistance(잠실역_교보문고_좌표); @@ -251,29 +234,29 @@ class GameServiceTest { void 플레이어_id와_게임_상태로_게임을_조회한다() { // given final Player player = playerBuilder.init() - .build(); + .build(); final Place destination = placeBuilder.init() - .position(잠실_루터회관_정문_좌표) - .build(); + .position(잠실_루터회관_정문_좌표) + .build(); final Game game1 = gameBuilder.init() - .place(destination) - .player(player) - .gameStatus(DONE) - .startTime(LocalDateTime.of(2023, Month.AUGUST, 13, 15, 30, 0)) - .endTime(LocalDateTime.of(2023, Month.AUGUST, 13, 17, 30, 0)) - .startPosition(잠실역_교보문고_좌표) - .build(); + .place(destination) + .player(player) + .gameStatus(DONE) + .startTime(LocalDateTime.of(2023, Month.AUGUST, 13, 15, 30, 0)) + .endTime(LocalDateTime.of(2023, Month.AUGUST, 13, 17, 30, 0)) + .startPosition(잠실역_교보문고_좌표) + .build(); final Game game2 = gameBuilder.init() - .place(destination) - .player(player) - .gameStatus(DONE) - .startTime(LocalDateTime.of(2023, Month.AUGUST, 12, 15, 30, 0)) - .endTime(LocalDateTime.of(2023, Month.AUGUST, 12, 17, 30, 0)) - .startPosition(잠실역_교보문고_좌표) - .build(); + .place(destination) + .player(player) + .gameStatus(DONE) + .startTime(LocalDateTime.of(2023, Month.AUGUST, 12, 15, 30, 0)) + .endTime(LocalDateTime.of(2023, Month.AUGUST, 12, 17, 30, 0)) + .startPosition(잠실역_교보문고_좌표) + .build(); // when List expected = gameService.findGamesByStatus(new FindGameByStatusCommand(player.getId(), DONE)); @@ -290,20 +273,20 @@ class GameServiceTest { void 게임id로_게임을_조회한다() { // given final Player player = playerBuilder.init() - .build(); + .build(); final Place destination = placeBuilder.init() - .position(잠실_루터회관_정문_좌표) - .build(); + .position(잠실_루터회관_정문_좌표) + .build(); final Game game = gameBuilder.init() - .place(destination) - .player(player) - .gameStatus(DONE) - .startTime(LocalDateTime.of(2023, Month.AUGUST, 13, 15, 30, 0)) - .endTime(LocalDateTime.of(2023, Month.AUGUST, 13, 17, 30, 0)) - .startPosition(잠실역_교보문고_좌표) - .build(); + .place(destination) + .player(player) + .gameStatus(DONE) + .startTime(LocalDateTime.of(2023, Month.AUGUST, 13, 15, 30, 0)) + .endTime(LocalDateTime.of(2023, Month.AUGUST, 13, 17, 30, 0)) + .startPosition(잠실역_교보문고_좌표) + .build(); // when Game expected = gameService.findGameById(new FindGameByIdCommand(game.getId(), player.getId())); @@ -318,24 +301,24 @@ class GameServiceTest { void 요청_플레이어의_id와_게임의_플레이어와_일치하지_않으면_예외가_발생한다() { // given final Player player1 = playerBuilder.init() - .build(); + .build(); final Player player2 = playerBuilder.init() - .nickname("코코닥") - .build(); + .nickname("코코닥") + .build(); final Place destination = placeBuilder.init() - .position(잠실_루터회관_정문_좌표) - .build(); + .position(잠실_루터회관_정문_좌표) + .build(); final Game game = gameBuilder.init() - .place(destination) - .player(player2) - .gameStatus(DONE) - .startTime(LocalDateTime.of(2023, Month.AUGUST, 13, 15, 30, 0)) - .endTime(LocalDateTime.of(2023, Month.AUGUST, 13, 17, 30, 0)) - .startPosition(잠실역_교보문고_좌표) - .build(); + .place(destination) + .player(player2) + .gameStatus(DONE) + .startTime(LocalDateTime.of(2023, Month.AUGUST, 13, 15, 30, 0)) + .endTime(LocalDateTime.of(2023, Month.AUGUST, 13, 17, 30, 0)) + .startPosition(잠실역_교보문고_좌표) + .build(); // when GameException gameException = assertThrows(GameException.class, () -> gameService.findGameById(new FindGameByIdCommand(game.getId(), player1.getId()))); @@ -348,20 +331,20 @@ class GameServiceTest { void 게임을_포기하면_게임을_종료한다() { // given final Player player = playerBuilder.init() - .build(); + .build(); final Place destination = placeBuilder.init() - .position(잠실_루터회관_정문_좌표) - .build(); + .position(잠실_루터회관_정문_좌표) + .build(); final Game game = gameBuilder.init() - .place(destination) - .player(player) - .gameStatus(IN_PROGRESS) - .startTime(LocalDateTime.of(2023, Month.AUGUST, 13, 15, 30, 0)) - .endTime(LocalDateTime.of(2023, Month.AUGUST, 13, 17, 30, 0)) - .startPosition(잠실역_교보문고_좌표) - .build(); + .place(destination) + .player(player) + .gameStatus(IN_PROGRESS) + .startTime(LocalDateTime.of(2023, Month.AUGUST, 13, 15, 30, 0)) + .endTime(LocalDateTime.of(2023, Month.AUGUST, 13, 17, 30, 0)) + .startPosition(잠실역_교보문고_좌표) + .build(); // when gameService.endGame(new EndGameCommand(player.getId(), GIVE_UP, 잠실_루터회관_정문_좌표, game.getId())); @@ -379,20 +362,20 @@ class GameServiceTest { void 목적지_주변에서_도착_도전하면_게임을_종료한다() { // given final Player player = playerBuilder.init() - .build(); + .build(); final Place destination = placeBuilder.init() - .position(잠실_루터회관_정문_좌표) - .build(); + .position(잠실_루터회관_정문_좌표) + .build(); final Game game = gameBuilder.init() - .place(destination) - .player(player) - .gameStatus(IN_PROGRESS) - .startTime(LocalDateTime.of(2023, Month.AUGUST, 13, 15, 30, 0)) - .endTime(LocalDateTime.of(2023, Month.AUGUST, 13, 17, 30, 0)) - .startPosition(잠실역_교보문고_좌표) - .build(); + .place(destination) + .player(player) + .gameStatus(IN_PROGRESS) + .startTime(LocalDateTime.of(2023, Month.AUGUST, 13, 15, 30, 0)) + .endTime(LocalDateTime.of(2023, Month.AUGUST, 13, 17, 30, 0)) + .startPosition(잠실역_교보문고_좌표) + .build(); // when gameService.endGame(new EndGameCommand(player.getId(), ARRIVED, 잠실_루터회관_정문_좌표, game.getId())); @@ -410,20 +393,20 @@ class GameServiceTest { void 종료요청이_들어왔을때_GameNotArrivalException이_발생해도_롤백되지않고_게임결과를_저장한다() { // given final Player player = playerBuilder.init() - .build(); + .build(); final Place destination = placeBuilder.init() - .position(잠실_루터회관_정문_좌표) - .build(); + .position(잠실_루터회관_정문_좌표) + .build(); final Game game = gameBuilder.init() - .place(destination) - .player(player) - .gameStatus(IN_PROGRESS) - .startTime(LocalDateTime.of(2023, Month.AUGUST, 13, 15, 30, 0)) - .startPosition(잠실역_교보문고_좌표) - .remainingAttempts(3) - .build(); + .place(destination) + .player(player) + .gameStatus(IN_PROGRESS) + .startTime(LocalDateTime.of(2023, Month.AUGUST, 13, 15, 30, 0)) + .startPosition(잠실역_교보문고_좌표) + .remainingAttempts(3) + .build(); // when & then final EndGameCommand endGameCommand = new EndGameCommand(player.getId(), ARRIVED, 역삼역_좌표, game.getId()); @@ -440,11 +423,11 @@ class GameServiceTest { void 게임생성_요청이_들어오면_게임을_저장하고_반환한다() { // given final Player player = playerBuilder.init() - .build(); + .build(); final Place destination = placeBuilder.init() - .position(장미_상가) - .build(); + .position(장미_상가) + .build(); // when final Game expected = gameService.createGame(new CreateGameCommand(player.getId(), 잠실_루터회관_정문_좌표)); @@ -457,21 +440,20 @@ class GameServiceTest { void 게임생성_요청이_들어왔을때_진행중인_게임이_있다면_예외를_발생시킨다() { // given final Player player = playerBuilder.init() - .build(); + .build(); final Place destination = placeBuilder.init() - .position(장미_상가) - .build(); + .position(장미_상가) + .build(); final Game game = gameBuilder.init() - .place(destination) - .player(player) - .gameStatus(IN_PROGRESS) - .startTime(LocalDateTime.of(2023, Month.AUGUST, 13, 15, 30, 0)) - .endTime(LocalDateTime.of(2023, Month.AUGUST, 13, 17, 30, 0)) - .startPosition(잠실역_교보문고_좌표) - .build(); - + .place(destination) + .player(player) + .gameStatus(IN_PROGRESS) + .startTime(LocalDateTime.of(2023, Month.AUGUST, 13, 15, 30, 0)) + .endTime(LocalDateTime.of(2023, Month.AUGUST, 13, 17, 30, 0)) + .startPosition(잠실역_교보문고_좌표) + .build(); // when GameException gameException = assertThrows(GameException.class, () -> gameService.createGame(new CreateGameCommand(player.getId(), 잠실역_교보문고_좌표))); @@ -484,7 +466,7 @@ class GameServiceTest { void 게임임생성_요청이_들어왔을때_추천장소가_없다면_예외를_발생시킨다() { // given final Player player = playerBuilder.init() - .build(); + .build(); // when GameException gameException = assertThrows(GameException.class, () -> gameService.createGame(new CreateGameCommand(player.getId(), 잠실역_교보문고_좌표))); diff --git a/backend/src/test/java/com/now/naaga/game/application/HintServiceTest.java b/backend/src/test/java/com/now/naaga/game/application/HintServiceTest.java index 351844d2e..6ba3e67d1 100644 --- a/backend/src/test/java/com/now/naaga/game/application/HintServiceTest.java +++ b/backend/src/test/java/com/now/naaga/game/application/HintServiceTest.java @@ -8,8 +8,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; -import com.now.naaga.common.builder.GameBuilder; -import com.now.naaga.common.builder.PlaceBuilder; +import com.now.naaga.common.ServiceTest; import com.now.naaga.common.exception.BaseExceptionType; import com.now.naaga.game.application.dto.CreateHintCommand; import com.now.naaga.game.application.dto.FindHintByIdCommand; @@ -19,32 +18,16 @@ import com.now.naaga.game.exception.GameException; import com.now.naaga.place.domain.Place; import java.time.LocalDateTime; -import org.junit.jupiter.api.DisplayNameGeneration; -import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.jdbc.Sql; import org.springframework.transaction.annotation.Transactional; @SuppressWarnings("NonAsciiCharacters") -@DisplayNameGeneration(ReplaceUnderscores.class) -@Sql("/truncate.sql") - -@ActiveProfiles("test") -@SpringBootTest -class HintServiceTest { +class HintServiceTest extends ServiceTest { @Autowired private HintService hintService; - @Autowired - private GameBuilder gameBuilder; - - @Autowired - private PlaceBuilder placeBuilder; - @Transactional @Test void 힌트를_생성한다() { diff --git a/backend/src/test/java/com/now/naaga/game/domain/GameTest.java b/backend/src/test/java/com/now/naaga/game/domain/GameTest.java index 38d15db49..cffae6444 100644 --- a/backend/src/test/java/com/now/naaga/game/domain/GameTest.java +++ b/backend/src/test/java/com/now/naaga/game/domain/GameTest.java @@ -28,7 +28,6 @@ import org.junit.jupiter.params.provider.ValueSource; import org.springframework.test.context.ActiveProfiles; -@ActiveProfiles("test") @SuppressWarnings("NonAsciiCharacters") @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) class GameTest { diff --git a/backend/src/test/java/com/now/naaga/game/domain/ResultScorePolicyTest.java b/backend/src/test/java/com/now/naaga/game/domain/ResultScorePolicyTest.java index 5291cad0c..57c5360c7 100644 --- a/backend/src/test/java/com/now/naaga/game/domain/ResultScorePolicyTest.java +++ b/backend/src/test/java/com/now/naaga/game/domain/ResultScorePolicyTest.java @@ -19,7 +19,6 @@ import org.junit.jupiter.api.Test; import org.springframework.test.context.ActiveProfiles; -@ActiveProfiles("test") @SuppressWarnings("NonAsciiCharacters") @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) class ResultScorePolicyTest { diff --git a/backend/src/test/java/com/now/naaga/game/domain/StatisticTest.java b/backend/src/test/java/com/now/naaga/game/domain/StatisticTest.java index 1f1ab2848..75016c04c 100644 --- a/backend/src/test/java/com/now/naaga/game/domain/StatisticTest.java +++ b/backend/src/test/java/com/now/naaga/game/domain/StatisticTest.java @@ -23,7 +23,6 @@ import org.junit.jupiter.api.Test; import org.springframework.test.context.ActiveProfiles; -@ActiveProfiles("test") @SuppressWarnings("NonAsciiCharacters") @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) class StatisticTest { diff --git a/backend/src/test/java/com/now/naaga/game/domain/gamescore/ResultScoreCalculatorTest.java b/backend/src/test/java/com/now/naaga/game/domain/gamescore/ResultScoreCalculatorTest.java index 45be29a23..782964b9b 100644 --- a/backend/src/test/java/com/now/naaga/game/domain/gamescore/ResultScoreCalculatorTest.java +++ b/backend/src/test/java/com/now/naaga/game/domain/gamescore/ResultScoreCalculatorTest.java @@ -10,23 +10,23 @@ import com.now.naaga.game.domain.Game; import com.now.naaga.game.domain.GameStatus; import com.now.naaga.gameresult.domain.ResultType; +import com.now.naaga.gameresult.domain.gamescore.FailResultScorePolicy; import com.now.naaga.gameresult.domain.gamescore.ResultScoreCalculator; +import com.now.naaga.gameresult.domain.gamescore.SuccessResultScorePolicy; import com.now.naaga.score.domain.Score; import java.time.LocalDateTime; import java.util.Collections; +import java.util.List; import org.junit.jupiter.api.DisplayNameGeneration; import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; @SuppressWarnings("NonAsciiCharacters") @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) -@SpringBootTest class ResultScoreCalculatorTest { - @Autowired - ResultScoreCalculator resultScoreCalculator; + ResultScoreCalculator resultScoreCalculator = new ResultScoreCalculator(List.of(new SuccessResultScorePolicy(), + new FailResultScorePolicy())); @Test void 게임결과가_성공일_때_점수를_얻는다() { diff --git a/backend/src/test/java/com/now/naaga/game/presentation/GameControllerTest.java b/backend/src/test/java/com/now/naaga/game/presentation/GameControllerTest.java index 5a1dcd656..64dc91bd2 100644 --- a/backend/src/test/java/com/now/naaga/game/presentation/GameControllerTest.java +++ b/backend/src/test/java/com/now/naaga/game/presentation/GameControllerTest.java @@ -21,15 +21,7 @@ import static com.now.naaga.gameresult.domain.ResultType.SUCCESS; import static org.assertj.core.api.SoftAssertions.assertSoftly; -import com.now.naaga.auth.domain.AuthToken; -import com.now.naaga.auth.infrastructure.AuthType; -import com.now.naaga.auth.infrastructure.jwt.AuthTokenGenerator; -import com.now.naaga.common.CommonControllerTest; -import com.now.naaga.common.builder.GameBuilder; -import com.now.naaga.common.builder.GameResultBuilder; -import com.now.naaga.common.builder.MemberBuilder; -import com.now.naaga.common.builder.PlaceBuilder; -import com.now.naaga.common.builder.PlayerBuilder; +import com.now.naaga.common.ControllerTest; import com.now.naaga.common.exception.ExceptionResponse; import com.now.naaga.game.domain.Direction; import com.now.naaga.game.domain.Game; @@ -41,8 +33,6 @@ import com.now.naaga.game.presentation.dto.GameResultResponse; import com.now.naaga.game.presentation.dto.GameStatusResponse; import com.now.naaga.game.presentation.dto.HintResponse; -import com.now.naaga.game.repository.GameRepository; -import com.now.naaga.game.repository.HintRepository; import com.now.naaga.gameresult.domain.GameResult; import com.now.naaga.member.domain.Member; import com.now.naaga.place.domain.Place; @@ -59,46 +49,12 @@ import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayNameGeneration; -import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; @SuppressWarnings("NonAsciiCharacters") -@DisplayNameGeneration(ReplaceUnderscores.class) -class GameControllerTest extends CommonControllerTest { - - @Autowired - private AuthTokenGenerator authTokenGenerator; - - @Autowired - private GameRepository gameRepository; - - @Autowired - private HintRepository hintRepository; - - @Autowired - private GameResultBuilder gameResultBuilder; - - @Autowired - private GameBuilder gameBuilder; - - @Autowired - private PlaceBuilder placeBuilder; - - @Autowired - private PlayerBuilder playerBuilder; - - @Autowired - private MemberBuilder memberBuilder; - - @BeforeEach - protected void setUp() { - super.setUp(); - } +class GameControllerTest extends ControllerTest { @Test void 게임_생성_요청시_진행중인_게임이_없으면서_주변에_추천_장소가_있다면_게임을_정상적으로_생성한다() { @@ -108,10 +64,7 @@ protected void setUp() { .build(); final Player player = playerBuilder.init() - .build(); - - final AuthToken generate = authTokenGenerator.generate(destination.getRegisteredPlayer().getMember(), 1L, AuthType.KAKAO); - final String accessToken = generate.getAccessToken(); + .build(); CoordinateRequest coordinateRequest = new CoordinateRequest(잠실역_교보문고_좌표.getLatitude().doubleValue(), 잠실역_교보문고_좌표.getLongitude().doubleValue()); @@ -119,7 +72,7 @@ protected void setUp() { // when final ExtractableResponse extract = RestAssured .given().log().all() - .header("Authorization", "Bearer " + accessToken) + .header("Authorization", authorizationForBearer(destination.getRegisteredPlayer())) .contentType(ContentType.JSON) .body(coordinateRequest) .when() @@ -171,16 +124,13 @@ protected void setUp() { .startPosition(잠실역_교보문고_좌표) .build(); - final AuthToken generate = authTokenGenerator.generate(player.getMember(), 1L, AuthType.KAKAO); - final String accessToken = generate.getAccessToken(); - CoordinateRequest coordinateRequest = new CoordinateRequest(잠실역_교보문고_좌표.getLatitude().doubleValue(), 잠실역_교보문고_좌표.getLongitude().doubleValue()); // when final ExtractableResponse extract = RestAssured .given().log().all() - .header("Authorization", "Bearer " + accessToken) + .header("Authorization", authorizationForBearer(player)) .contentType(ContentType.JSON) .body(coordinateRequest) .when() @@ -208,10 +158,7 @@ protected void setUp() { void 게임_생성_요청시_주변에_추천_장소가_없다면_예외가_발생한다() { // given final Player player = playerBuilder.init() - .build(); - - final AuthToken generate = authTokenGenerator.generate(player.getMember(), 1L, AuthType.KAKAO); - final String accessToken = generate.getAccessToken(); + .build(); CoordinateRequest coordinateRequest = new CoordinateRequest(역삼역_좌표.getLatitude().doubleValue(), 역삼역_좌표.getLongitude().doubleValue()); @@ -219,7 +166,7 @@ protected void setUp() { // when final ExtractableResponse extract = RestAssured .given().log().all() - .header("Authorization", "Bearer " + accessToken) + .header("Authorization", authorizationForBearer(player)) .contentType(ContentType.JSON) .body(coordinateRequest) .when() @@ -257,14 +204,9 @@ protected void setUp() { .startPosition(잠실역_교보문고_좌표) .build(); - - final AuthToken generate = authTokenGenerator.generate(player.getMember(), 1L, AuthType.KAKAO); - final String accessToken = generate.getAccessToken(); - Thread.sleep(1000); - final ExtractableResponse extract = RestAssured .given().log().all() - .header("Authorization", "Bearer " + accessToken) + .header("Authorization", authorizationForBearer(player)) .contentType(ContentType.JSON) .body(new EndGameRequest("GIVE_UP", new CoordinateRequest(37.515546, 127.102902)))// 역삼역 좌표 .when() @@ -306,13 +248,9 @@ protected void setUp() { .startPosition(잠실역_교보문고_좌표) .build(); - final AuthToken generate = authTokenGenerator.generate(player.getMember(), 1L, AuthType.KAKAO); - final String accessToken = generate.getAccessToken(); - Thread.sleep(1000); - final ExtractableResponse extract = RestAssured .given().log().all() - .header("Authorization", "Bearer " + accessToken) + .header("Authorization", authorizationForBearer(player)) .contentType(ContentType.JSON) .body(new EndGameRequest("ARRIVED", new CoordinateRequest(37.515546, 127.102902))) .when() @@ -354,18 +292,15 @@ protected void setUp() { .remainingAttempts(1) .build(); - final AuthToken generate = authTokenGenerator.generate(player.getMember(), 1L, AuthType.KAKAO); - final String accessToken = generate.getAccessToken(); - Thread.sleep(1000); - - final ExtractableResponse extract = RestAssured.given().log().all() - .header("Authorization", "Bearer " + accessToken) - .contentType(ContentType.JSON) - .body(new EndGameRequest("ARRIVED", new CoordinateRequest(37.500845, 127.036953)))// 역삼역 좌표 - .when() - .patch("/games/{gameId}", game.getId()) - .then().log().all() - .extract(); + final ExtractableResponse extract = RestAssured + .given().log().all() + .header("Authorization", authorizationForBearer(player)) + .contentType(ContentType.JSON) + .body(new EndGameRequest("ARRIVED", new CoordinateRequest(37.500845, 127.036953)))// 역삼역 좌표 + .when() + .patch("/games/{gameId}", game.getId()) + .then().log().all() + .extract(); // then final int statusCode = extract.statusCode(); @@ -399,14 +334,11 @@ protected void setUp() { .startPosition(잠실역_교보문고_좌표) .build(); - final AuthToken generate = authTokenGenerator.generate(player.getMember(), 1L, AuthType.KAKAO); - final String accessToken = generate.getAccessToken(); - final int beforeRemainingAttempts = game.getRemainingAttempts(); final ExtractableResponse extract = RestAssured .given().log().all() - .header("Authorization", "Bearer " + accessToken) + .header("Authorization", authorizationForBearer(player)) .contentType(ContentType.JSON) .body(new EndGameRequest("ARRIVED", new CoordinateRequest(37.500845, 127.036953)))// 역삼역 좌표 .when() @@ -416,7 +348,7 @@ protected void setUp() { final ExtractableResponse extractAfter = RestAssured .given().log().all() - .header("Authorization", "Bearer " + accessToken) + .header("Authorization", authorizationForBearer(player)) .when() .get("/games/{gameId}", game.getId()) .then().log().all() @@ -455,9 +387,6 @@ protected void setUp() { .startPosition(잠실역_교보문고_좌표) .build(); - final AuthToken generate = authTokenGenerator.generate(player.getMember(), 1L, AuthType.KAKAO); - final String accessToken = generate.getAccessToken(); - final ExtractableResponse extract = RestAssured .given().log().all() .contentType(ContentType.JSON) @@ -516,15 +445,12 @@ protected void setUp() { .startPosition(잠실역_교보문고_좌표) .build(); - final AuthToken generate = authTokenGenerator.generate(player2.getMember(), 1L, AuthType.KAKAO); - final String accessToken = generate.getAccessToken(); - final CoordinateRequest coordinateRequest = new CoordinateRequest(잠실_루터회관_정문_근처_좌표.getLatitude().doubleValue(), 잠실_루터회관_정문_근처_좌표.getLongitude().doubleValue()); final ExtractableResponse extract = RestAssured .given().log().all() - .header("Authorization", "Bearer " + accessToken) + .header("Authorization", authorizationForBearer(player2)) .contentType(ContentType.JSON) .body(new EndGameRequest("ARRIVED", coordinateRequest)) .when() @@ -558,12 +484,9 @@ protected void setUp() { .player(player) .build(); - final AuthToken generate = authTokenGenerator.generate(player.getMember(), 1L, AuthType.KAKAO); - final String accessToken = generate.getAccessToken(); - final ExtractableResponse extract = RestAssured .given().log().all() - .header("Authorization", "Bearer " + accessToken) + .header("Authorization", authorizationForBearer(player)) .contentType(ContentType.JSON) .body(new EndGameRequest("ARRIVED", new CoordinateRequest(37.515546, 127.102902))) .when() @@ -603,12 +526,9 @@ protected void setUp() { .startPosition(잠실역_교보문고_좌표) .build(); - final AuthToken generate = authTokenGenerator.generate(player.getMember(), 1L, AuthType.KAKAO); - final String accessToken = generate.getAccessToken();; - final ExtractableResponse extract = RestAssured .given().log().all() - .header("Authorization", "Bearer " + accessToken) + .header("Authorization", authorizationForBearer(player)) .when() .get("/games/{gameId}", game.getId()) .then().log().all() @@ -635,12 +555,9 @@ protected void setUp() { final Player player = playerBuilder.init() .build(); - final AuthToken generate = authTokenGenerator.generate(player.getMember(), 1L, AuthType.KAKAO); - final String accessToken = generate.getAccessToken();; - final ExtractableResponse extract = RestAssured .given().log().all() - .header("Authorization", "Bearer " + accessToken) + .header("Authorization", authorizationForBearer(player)) .contentType(ContentType.JSON) .when() .get("/games/{gameId}", 1L) @@ -680,19 +597,16 @@ protected void setUp() { .game(game) .build(); - final AuthToken generate = authTokenGenerator.generate(player.getMember(), 1L, AuthType.KAKAO); - final String accessToken = generate.getAccessToken(); - // when - final ExtractableResponse response = RestAssured.given() - .log().all() - .contentType(MediaType.APPLICATION_JSON_VALUE) - .header("Authorization", "Bearer " + accessToken) - .pathParam("gameId", game.getId()) - .when() - .get("/games/{gameId}/result", game.getId()) - .then().log().all() - .extract(); + final ExtractableResponse response = RestAssured + .given().log().all() + .header("Authorization", authorizationForBearer(player)) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .pathParam("gameId", game.getId()) + .when() + .get("/games/{gameId}/result", game.getId()) + .then().log().all() + .extract(); // then final GameResultResponse actual = response.as(GameResultResponse.class); @@ -736,20 +650,18 @@ protected void setUp() { .game(game2) .build(); - final AuthToken generate = authTokenGenerator.generate(player.getMember(), 1L, AuthType.KAKAO); - final String accessToken = generate.getAccessToken(); - // when - final ExtractableResponse response = RestAssured.given().log().all() - .contentType(MediaType.APPLICATION_JSON_VALUE) - .header("Authorization", "Bearer " + accessToken) - .param("sort-by", "time") - .param("order", "descending") - .when() - .get("/games/results") - .then().log().all() - .statusCode(HttpStatus.OK.value()) - .extract(); + final ExtractableResponse response = RestAssured + .given().log().all() + .header("Authorization", authorizationForBearer(player)) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .param("sort-by", "time") + .param("order", "descending") + .when() + .get("/games/results") + .then().log().all() + .statusCode(HttpStatus.OK.value()) + .extract(); // then final List actual = response.as(new TypeRef<>() { @@ -779,20 +691,18 @@ protected void setUp() { .startPosition(서울_좌표) .build(); - final AuthToken generate = authTokenGenerator.generate(game.getPlayer().getMember(), 1L, AuthType.KAKAO); - final String accessToken = generate.getAccessToken(); - final CoordinateRequest SEOUL_COORDINATE = new CoordinateRequest(서울_좌표.getLatitude().doubleValue(), 서울_좌표.getLongitude().doubleValue()); - final ExtractableResponse extract = RestAssured.given().log().all() - .header("Authorization", "Bearer " + accessToken) - .contentType(ContentType.JSON) - .body(SEOUL_COORDINATE) - .when() - .post("/games/{gameId}/hints", game.getId()) - .then().log().all() - .extract(); + final ExtractableResponse extract = RestAssured + .given().log().all() + .header("Authorization", authorizationForBearer(game.getPlayer())) + .contentType(ContentType.JSON) + .body(SEOUL_COORDINATE) + .when() + .post("/games/{gameId}/hints", game.getId()) + .then().log().all() + .extract(); // then final int statusCode = extract.statusCode(); @@ -827,12 +737,9 @@ protected void setUp() { final Hint hint = hintRepository.save(new Hint(서울_좌표, Direction.SOUTH, game)); - final AuthToken generate = authTokenGenerator.generate(game.getPlayer().getMember(), 1L, AuthType.KAKAO); - final String accessToken = generate.getAccessToken(); - final ExtractableResponse extract = RestAssured .given().log().all() - .header("Authorization", "Bearer " + accessToken) + .header("Authorization", authorizationForBearer(game.getPlayer())) .when() .get("/games/{gameId}/hints/{hintId}", game.getId(), hint.getId()) .then().log().all() @@ -858,24 +765,21 @@ protected void setUp() { public void 힌트_id를_통해_힌트를_조회할때_힌트가_존재하지_않으면_예외를_발생시킨다() { // given & when final Place place = placeBuilder.init() - .position(제주_좌표) - .build(); + .position(제주_좌표) + .build(); final Game game = gameBuilder.init() - .place(place) - .startPosition(서울_좌표) - .build(); + .place(place) + .startPosition(서울_좌표) + .build(); final Hint hint = hintRepository.save(new Hint(서울_좌표, Direction.SOUTH, game)); hintRepository.delete(hint); - final AuthToken generate = authTokenGenerator.generate(game.getPlayer().getMember(), 1L, AuthType.KAKAO); - final String accessToken = generate.getAccessToken(); - final ExtractableResponse extract = RestAssured .given().log().all() - .header("Authorization", "Bearer " + accessToken) + .header("Authorization", authorizationForBearer(game.getPlayer())) .when() .get("/games/{gameId}/hints/{hintId}", game.getId(), hint.getId()) .then().log().all() @@ -890,10 +794,10 @@ protected void setUp() { assertSoftly(softAssertions -> { softAssertions.assertThat(statusCode).isEqualTo(HttpStatus.NOT_FOUND.value()); softAssertions.assertThat(actual) - .usingRecursiveComparison() - .ignoringExpectedNullFields() - .ignoringFieldsOfTypes(LocalDateTime.class) - .isEqualTo(expected); + .usingRecursiveComparison() + .ignoringExpectedNullFields() + .ignoringFieldsOfTypes(LocalDateTime.class) + .isEqualTo(expected); }); } } diff --git a/backend/src/test/java/com/now/naaga/game/presentation/StatisticControllerTest.java b/backend/src/test/java/com/now/naaga/game/presentation/StatisticControllerTest.java index 53808d3ea..f201ce966 100644 --- a/backend/src/test/java/com/now/naaga/game/presentation/StatisticControllerTest.java +++ b/backend/src/test/java/com/now/naaga/game/presentation/StatisticControllerTest.java @@ -4,13 +4,7 @@ import static com.now.naaga.common.fixture.PositionFixture.잠실역_교보문고_좌표; import static org.assertj.core.api.SoftAssertions.assertSoftly; -import com.now.naaga.auth.domain.AuthToken; -import com.now.naaga.auth.infrastructure.AuthType; -import com.now.naaga.auth.infrastructure.jwt.AuthTokenGenerator; -import com.now.naaga.common.CommonControllerTest; -import com.now.naaga.common.builder.GameBuilder; -import com.now.naaga.common.builder.PlaceBuilder; -import com.now.naaga.common.builder.PlayerBuilder; +import com.now.naaga.common.ControllerTest; import com.now.naaga.game.application.GameService; import com.now.naaga.game.application.dto.EndGameCommand; import com.now.naaga.game.domain.EndType; @@ -23,38 +17,17 @@ import io.restassured.RestAssured; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayNameGeneration; -import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; @SuppressWarnings("NonAsciiCharacters") -@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) -public class StatisticControllerTest extends CommonControllerTest { +public class StatisticControllerTest extends ControllerTest { @Autowired private GameService gameService; - @Autowired - private AuthTokenGenerator authTokenGenerator; - - @Autowired - private GameBuilder gameBuilder; - - @Autowired - private PlaceBuilder placeBuilder; - - @Autowired - private PlayerBuilder playerBuilder; - - @BeforeEach - protected void setUp() { - super.setUp(); - } - @Test void 맴버의_통계를_조회한다() { //given @@ -94,17 +67,15 @@ protected void setUp() { final Statistic statistic = gameService.findStatistic(new PlayerRequest(player.getId())); - final AuthToken generate = authTokenGenerator.generate(player.getMember(), 1L, AuthType.KAKAO); - final String accessToken = generate.getAccessToken(); - // when - final ExtractableResponse response = RestAssured.given().log().all() - .contentType(MediaType.APPLICATION_JSON_VALUE) - .header("Authorization", "Bearer " + accessToken) - .when().get("/statistics/my") - .then().log().all() - .statusCode(HttpStatus.OK.value()) - .extract(); + final ExtractableResponse response = RestAssured + .given().log().all() + .header("Authorization", authorizationForBearer(player)) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .when().get("/statistics/my") + .then().log().all() + .statusCode(HttpStatus.OK.value()) + .extract(); // then final StatisticResponse actual = response.as(StatisticResponse.class); diff --git a/backend/src/test/java/com/now/naaga/gameresult/application/GameResultServiceTest.java b/backend/src/test/java/com/now/naaga/gameresult/application/GameResultServiceTest.java index cc7aeb026..bcd5cc258 100644 --- a/backend/src/test/java/com/now/naaga/gameresult/application/GameResultServiceTest.java +++ b/backend/src/test/java/com/now/naaga/gameresult/application/GameResultServiceTest.java @@ -6,53 +6,26 @@ import static com.now.naaga.gameresult.domain.ResultType.SUCCESS; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import com.now.naaga.common.builder.GameBuilder; -import com.now.naaga.common.builder.GameResultBuilder; -import com.now.naaga.common.builder.PlaceBuilder; -import com.now.naaga.common.builder.PlayerBuilder; +import com.now.naaga.common.ServiceTest; import com.now.naaga.game.application.dto.CreateGameResultCommand; import com.now.naaga.game.domain.Game; import com.now.naaga.game.exception.GameException; import com.now.naaga.gameresult.domain.GameResult; -import com.now.naaga.gameresult.repository.GameResultRepository; import com.now.naaga.place.domain.Position; import com.now.naaga.player.domain.Player; import com.now.naaga.score.domain.Score; import java.time.LocalDateTime; import org.assertj.core.api.SoftAssertions; -import org.junit.jupiter.api.DisplayNameGeneration; -import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.jdbc.Sql; import org.springframework.transaction.annotation.Transactional; -@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) -@Sql("/truncate.sql") -@ActiveProfiles("test") -@SpringBootTest -class GameResultServiceTest { - - @Autowired - private GameResultRepository gameResultRepository; +@SuppressWarnings("NonAsciiCharacters") +class GameResultServiceTest extends ServiceTest { @Autowired private GameResultService gameResultService; - @Autowired - private GameBuilder gameBuilder; - - @Autowired - private GameResultBuilder gameResultBuilder; - - @Autowired - private PlayerBuilder playerBuilder; - - @Autowired - private PlaceBuilder placeBuilder; - @Test @Transactional void 사용자의_위치가_도착_범위_안이고_엔트타입이_도착이면_게임_결과를_성공으로_생성_후_저장하고_플레이어의_점수를_올린다() { diff --git a/backend/src/test/java/com/now/naaga/gameresult/repository/GameResultRepositoryTest.java b/backend/src/test/java/com/now/naaga/gameresult/repository/GameResultRepositoryTest.java index c4b42d429..f650302c5 100644 --- a/backend/src/test/java/com/now/naaga/gameresult/repository/GameResultRepositoryTest.java +++ b/backend/src/test/java/com/now/naaga/gameresult/repository/GameResultRepositoryTest.java @@ -6,72 +6,52 @@ import static com.now.naaga.gameresult.domain.ResultType.SUCCESS; import static org.assertj.core.api.Assertions.assertThat; -import com.now.naaga.common.builder.GameBuilder; -import com.now.naaga.common.builder.GameResultBuilder; -import com.now.naaga.common.builder.PlaceBuilder; -import com.now.naaga.common.builder.PlayerBuilder; +import com.now.naaga.common.AbstractTest; import com.now.naaga.game.domain.Game; import com.now.naaga.gameresult.domain.GameResult; import com.now.naaga.place.domain.Place; import com.now.naaga.player.domain.Player; import java.util.List; -import org.junit.jupiter.api.DisplayNameGeneration; -import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.jdbc.Sql; -@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) -@Sql("/truncate.sql") +@SuppressWarnings("NonAsciiCharacters") @SpringBootTest -class GameResultRepositoryTest { - - @Autowired - private GameResultRepository gameResultRepository; - - @Autowired - private PlayerBuilder playerBuilder; - @Autowired - private PlaceBuilder placeBuilder; - @Autowired - private GameResultBuilder gameResultBuilder; - @Autowired - private GameBuilder gameBuilder; +class GameResultRepositoryTest extends AbstractTest { @Test void 맴버아이디로_게임결과를_조회했을때_게임결과에_모든정보가_조회된다() { //given final Player player = playerBuilder.init() - .build(); + .build(); final Place place = placeBuilder.init() - .position(잠실역_교보문고_좌표) - .registeredPlayer(player) - .build(); + .position(잠실역_교보문고_좌표) + .registeredPlayer(player) + .build(); final Game game1 = gameBuilder.init() - .startPosition(잠실_루터회관_정문_좌표) - .player(player) - .place(place) - .gameStatus(DONE) - .build(); + .startPosition(잠실_루터회관_정문_좌표) + .player(player) + .place(place) + .gameStatus(DONE) + .build(); final Game game2 = gameBuilder.init() - .startPosition(잠실_루터회관_정문_좌표) - .player(player) - .place(place) - .gameStatus(DONE) - .build(); + .startPosition(잠실_루터회관_정문_좌표) + .player(player) + .place(place) + .gameStatus(DONE) + .build(); final GameResult gameResult1 = gameResultBuilder.init() - .resultType(SUCCESS) - .game(game1) - .build(); + .resultType(SUCCESS) + .game(game1) + .build(); final GameResult gameResult2 = gameResultBuilder.init() - .resultType(SUCCESS) - .game(game2) - .build(); + .resultType(SUCCESS) + .game(game2) + .build(); // when List gameResults = gameResultRepository.findByPlayerId(player.getId()); diff --git a/backend/src/test/java/com/now/naaga/letter/application/LetterServiceTest.java b/backend/src/test/java/com/now/naaga/letter/application/LetterServiceTest.java index 3b7cb4ca7..4b774398e 100644 --- a/backend/src/test/java/com/now/naaga/letter/application/LetterServiceTest.java +++ b/backend/src/test/java/com/now/naaga/letter/application/LetterServiceTest.java @@ -1,9 +1,19 @@ package com.now.naaga.letter.application; -import com.now.naaga.common.builder.GameBuilder; -import com.now.naaga.common.builder.LetterBuilder; -import com.now.naaga.common.builder.PlaceBuilder; -import com.now.naaga.common.builder.PlayerBuilder; +import static com.now.naaga.common.fixture.PositionFixture.잠실_루터회관_정문_좌표; +import static com.now.naaga.common.fixture.PositionFixture.잠실역_교보문고_110미터_앞_좌표; +import static com.now.naaga.common.fixture.PositionFixture.잠실역_교보문고_좌표; +import static com.now.naaga.game.exception.GameExceptionType.NOT_EXIST_IN_PROGRESS; +import static com.now.naaga.letter.exception.LetterExceptionType.NO_EXIST; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.SoftAssertions.assertSoftly; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.atLeast; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +import com.now.naaga.common.ServiceTest; import com.now.naaga.common.exception.BaseExceptionType; import com.now.naaga.game.domain.Game; import com.now.naaga.game.domain.GameStatus; @@ -11,171 +21,136 @@ import com.now.naaga.game.exception.GameExceptionType; import com.now.naaga.letter.application.dto.CreateLetterCommand; import com.now.naaga.letter.domain.Letter; -import com.now.naaga.letter.domain.letterlog.LetterLogType; import com.now.naaga.letter.domain.letterlog.ReadLetterLog; import com.now.naaga.letter.exception.LetterException; import com.now.naaga.letter.presentation.dto.FindNearByLetterCommand; import com.now.naaga.letter.presentation.dto.LetterReadCommand; -import com.now.naaga.letter.repository.letterlog.ReadLetterLogRepository; import com.now.naaga.place.domain.Place; import com.now.naaga.place.domain.Position; import com.now.naaga.player.domain.Player; +import java.util.List; import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.DisplayNameGeneration; -import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.jdbc.Sql; import org.springframework.transaction.annotation.Transactional; -import java.util.List; - -import static com.now.naaga.common.fixture.PositionFixture.*; -import static com.now.naaga.game.exception.GameExceptionType.NOT_EXIST_IN_PROGRESS; -import static com.now.naaga.letter.exception.LetterExceptionType.NO_EXIST; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.assertj.core.api.SoftAssertions.assertSoftly; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.*; - -@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) -@ActiveProfiles("test") -@Sql("/truncate.sql") -@SpringBootTest -class LetterServiceTest { +@SuppressWarnings("NonAsciiCharacters") +class LetterServiceTest extends ServiceTest { @Autowired private LetterService letterService; - @Autowired - private PlayerBuilder playerBuilder; - - @Autowired - private GameBuilder gameBuilder; - - @Autowired - private ReadLetterLogRepository readLetterLogRepository; - - @Autowired - private PlaceBuilder placeBuilder; - - @Autowired - private LetterBuilder letterBuilder; - @Test void 이미_읽은_쪽지의_경우_읽은_쪽지_로그를_기록하지_않는다() { // given final Player player = playerBuilder.init() .build(); - + final Place destination = placeBuilder.init() .position(잠실_루터회관_정문_좌표) .build(); - + final Game game = gameBuilder.init() .place(destination) .player(player) .startPosition(잠실역_교보문고_좌표) .build(); - + final Player letterRegister = playerBuilder.init() .build(); - + final Letter letter = letterBuilder.init() .registeredPlayer(letterRegister) .build(); - + LetterService mockReadLetterService = mock(LetterService.class); - + // when mockReadLetterService.findLetter(new LetterReadCommand(player.getId(), letter.getId())); mockReadLetterService.findLetter(new LetterReadCommand(player.getId(), letter.getId())); - + //then verify(mockReadLetterService, atLeast(1)).findLetter(new LetterReadCommand(player.getId(), letter.getId())); } - + @Test void 읽은_쪽지_로그를_정상적으로_기록한다() { // given final Player player = playerBuilder.init() .build(); - + final Place destination = placeBuilder.init() .position(잠실_루터회관_정문_좌표) .build(); - + final Game game = gameBuilder.init() .place(destination) .player(player) .startPosition(잠실역_교보문고_좌표) .build(); - + final Player letterRegister = playerBuilder.init() .build(); - + final Letter letter = letterBuilder.init() .registeredPlayer(letterRegister) .build(); - + // when letterService.findLetter(new LetterReadCommand(player.getId(), letter.getId())); - + // then final List actual = readLetterLogRepository.findAll(); final long expected = actual.get(0).getLetter().getId(); - + assertSoftly(softAssertions -> { softAssertions.assertThat(actual).hasSize(1); softAssertions.assertThat(expected).isEqualTo(letter.getId()); }); } - - + + @Test void 읽은쪽지로그에_데이터저장시_진행중인_게임이없으면_예외가_발생한다() { // given && when final Player player = playerBuilder.init() .build(); - + final Place destination = placeBuilder.init() .position(잠실_루터회관_정문_좌표) .build(); - + final Game game = gameBuilder.init() .place(destination) .player(player) .startPosition(잠실역_교보문고_좌표) .gameStatus(GameStatus.DONE) .build(); - + final Player letterRegister = playerBuilder.init() .build(); - + final Letter letter = letterBuilder.init() .registeredPlayer(letterRegister) .build(); - + //then final GameException gameException = assertThrows( GameException.class, () -> letterService.findLetter(new LetterReadCommand(player.getId(), letter.getId()))); assertThat(gameException.exceptionType()).isEqualTo(NOT_EXIST_IN_PROGRESS); } - + @Transactional @Test void 쪽지를_정상적으로_생성하고_게임중_등록한_쪽지를_기록으로_남긴다() { //given final Player savedPlayer = playerBuilder.init() - .build(); + .build(); final String message = "날씨가 선선해요."; final Position position = 잠실_루터회관_정문_좌표; gameBuilder.init() - .player(savedPlayer) - .build(); + .player(savedPlayer) + .build(); //when final CreateLetterCommand createLetterCommand = new CreateLetterCommand( @@ -188,9 +163,9 @@ class LetterServiceTest { //then assertSoftly(softAssertions -> { softAssertions.assertThat(actual) - .usingRecursiveComparison() - .ignoringExpectedNullFields() - .isEqualTo(expected); + .usingRecursiveComparison() + .ignoringExpectedNullFields() + .isEqualTo(expected); }); } @@ -198,7 +173,7 @@ class LetterServiceTest { void 쪽지를_등록할_때_현재_진행_중인_게임이_존재하지_않으면_예외가_발생한다() { //given final Player savedPlayer = playerBuilder.init() - .build(); + .build(); final String message = "날씨가 선선해요."; final Position position = 잠실_루터회관_정문_좌표; final CreateLetterCommand createLetterCommand = new CreateLetterCommand( @@ -220,16 +195,16 @@ class LetterServiceTest { void 플레이어주변_100m_내로의_쪽지만_모두_조회한다() { // given final Player registerPlayer = playerBuilder.init() - .build(); + .build(); final Letter letter1 = letterBuilder.init() - .registeredPlayer(registerPlayer) - .build(); + .registeredPlayer(registerPlayer) + .build(); final Letter letter2 = letterBuilder.init() - .registeredPlayer(registerPlayer) - .position(잠실역_교보문고_110미터_앞_좌표) - .build(); + .registeredPlayer(registerPlayer) + .position(잠실역_교보문고_110미터_앞_좌표) + .build(); // when final List actual = letterService.findNearByLetters(new FindNearByLetterCommand(잠실역_교보문고_좌표)); @@ -245,12 +220,12 @@ class LetterServiceTest { void 플레이어주변_100m_내로의_쪽지가_없으면_빈리스트를_반환한다() { // given final Player registerPlayer = playerBuilder.init() - .build(); + .build(); final Letter letter = letterBuilder.init() - .registeredPlayer(registerPlayer) - .position(잠실역_교보문고_110미터_앞_좌표) - .build(); + .registeredPlayer(registerPlayer) + .position(잠실역_교보문고_110미터_앞_좌표) + .build(); // when final List actual = letterService.findNearByLetters(new FindNearByLetterCommand(잠실_루터회관_정문_좌표)); @@ -263,30 +238,29 @@ class LetterServiceTest { void 쪽지를_단건조회_한다() { // given final Player player = playerBuilder.init() - .build(); + .build(); final Place destination = placeBuilder.init() - .position(잠실_루터회관_정문_좌표) - .build(); + .position(잠실_루터회관_정문_좌표) + .build(); final Game game = gameBuilder.init() - .place(destination) - .player(player) - .startPosition(잠실역_교보문고_좌표) - .build(); + .place(destination) + .player(player) + .startPosition(잠실역_교보문고_좌표) + .build(); final Player letterRegister = playerBuilder.init() - .build(); + .build(); final Letter letter = letterBuilder.init() - .registeredPlayer(letterRegister) - .build(); + .registeredPlayer(letterRegister) + .build(); // when final Letter actual = letterService.findLetter(new LetterReadCommand(player.getId(), letter.getId())); final List actualLog = readLetterLogRepository.findAll(); - // then assertSoftly(softAssertions -> { softAssertions.assertThat(actual.getId()).isEqualTo(letter.getId()); @@ -298,24 +272,24 @@ class LetterServiceTest { void 쪽지가_존재하지_않으면_예외가_발생한다() { // given & when final Player player = playerBuilder.init() - .build(); + .build(); final Place destination = placeBuilder.init() - .position(잠실_루터회관_정문_좌표) - .build(); + .position(잠실_루터회관_정문_좌표) + .build(); final Game game = gameBuilder.init() - .place(destination) - .player(player) - .startPosition(잠실역_교보문고_좌표) - .build(); + .place(destination) + .player(player) + .startPosition(잠실역_교보문고_좌표) + .build(); final Player letterRegister = playerBuilder.init() - .build(); + .build(); final Letter letter = letterBuilder.init() - .registeredPlayer(letterRegister) - .build(); + .registeredPlayer(letterRegister) + .build(); // then final LetterException letterException = assertThrows( diff --git a/backend/src/test/java/com/now/naaga/letter/presentation/LetterControllerTest.java b/backend/src/test/java/com/now/naaga/letter/presentation/LetterControllerTest.java index c3e17cc0a..fe11afce5 100644 --- a/backend/src/test/java/com/now/naaga/letter/presentation/LetterControllerTest.java +++ b/backend/src/test/java/com/now/naaga/letter/presentation/LetterControllerTest.java @@ -1,22 +1,27 @@ package com.now.naaga.letter.presentation; -import com.now.naaga.auth.domain.AuthToken; -import com.now.naaga.auth.infrastructure.AuthType; -import com.now.naaga.auth.infrastructure.jwt.AuthTokenGenerator; -import com.now.naaga.common.CommonControllerTest; -import com.now.naaga.common.builder.*; +import static com.now.naaga.common.exception.CommonExceptionType.INVALID_REQUEST_BODY; +import static com.now.naaga.common.exception.CommonExceptionType.INVALID_REQUEST_PARAMETERS; +import static com.now.naaga.common.fixture.PositionFixture.GS25_방이도곡점_좌표; +import static com.now.naaga.common.fixture.PositionFixture.역삼역_좌표; +import static com.now.naaga.common.fixture.PositionFixture.잠실_루터회관_정문_좌표; +import static com.now.naaga.common.fixture.PositionFixture.잠실역_교보문고_110미터_앞_좌표; +import static com.now.naaga.common.fixture.PositionFixture.잠실역_교보문고_좌표; +import static com.now.naaga.game.domain.GameStatus.DONE; +import static com.now.naaga.game.exception.GameExceptionType.NOT_EXIST_IN_PROGRESS; +import static com.now.naaga.player.exception.PlayerExceptionType.PLAYER_NOT_FOUND; +import static org.assertj.core.api.SoftAssertions.assertSoftly; + +import com.now.naaga.common.ControllerTest; import com.now.naaga.common.exception.ExceptionResponse; import com.now.naaga.game.domain.Game; import com.now.naaga.game.presentation.dto.CoordinateResponse; -import com.now.naaga.game.repository.GameRepository; -import com.now.naaga.letter.application.LetterService; import com.now.naaga.letter.domain.Letter; import com.now.naaga.letter.domain.letterlog.ReadLetterLog; import com.now.naaga.letter.domain.letterlog.WriteLetterLog; import com.now.naaga.letter.presentation.dto.LetterRequest; import com.now.naaga.letter.presentation.dto.LetterResponse; import com.now.naaga.letter.presentation.dto.NearByLetterResponse; -import com.now.naaga.letter.repository.LetterRepository; import com.now.naaga.member.domain.Member; import com.now.naaga.place.domain.Place; import com.now.naaga.player.domain.Player; @@ -26,66 +31,17 @@ import io.restassured.http.ContentType; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayNameGeneration; -import org.junit.jupiter.api.DisplayNameGenerator; +import java.time.LocalDateTime; +import java.util.List; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; -import java.time.LocalDateTime; -import java.util.List; - -import static com.now.naaga.common.exception.CommonExceptionType.INVALID_REQUEST_BODY; -import static com.now.naaga.common.exception.CommonExceptionType.INVALID_REQUEST_PARAMETERS; -import static com.now.naaga.common.fixture.PositionFixture.*; -import static com.now.naaga.game.domain.GameStatus.DONE; -import static com.now.naaga.game.exception.GameExceptionType.NOT_EXIST_IN_PROGRESS; -import static com.now.naaga.player.exception.PlayerExceptionType.PLAYER_NOT_FOUND; -import static org.assertj.core.api.SoftAssertions.assertSoftly; - @SuppressWarnings("NonAsciiCharacters") -@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) -class LetterControllerTest extends CommonControllerTest { - - @Autowired - private AuthTokenGenerator authTokenGenerator; - - @Autowired - private GameRepository gameRepository; - - @Autowired - private LetterService letterService; - - @Autowired - private LetterRepository letterRepository; - - @Autowired - private GameBuilder gameBuilder; - - @Autowired - private LetterBuilder letterBuilder; - - @Autowired - private ReadLetterLogBuilder readLetterLogBuilder; - - @Autowired - private WriteLetterLogBuilder writeLetterLogBuilder; - - @Autowired - private PlaceBuilder placeBuilder; - - @Autowired - private PlayerBuilder playerBuilder; - - @BeforeEach - protected void setUp() { - super.setUp(); - } - +class LetterControllerTest extends ControllerTest { + @Test void 주변_쪽지를_모두_조회한다() { // given @@ -98,28 +54,26 @@ protected void setUp() { final Letter letter2 = letterBuilder.init() .position(잠실역_교보문고_110미터_앞_좌표) .build(); - - final AuthToken generate = authTokenGenerator.generate(destination.getRegisteredPlayer().getMember(), 1L, AuthType.KAKAO); - final String accessToken = generate.getAccessToken(); - + // when - final ExtractableResponse extract = RestAssured.given().log().all() - .contentType(MediaType.APPLICATION_JSON_VALUE) - .header("Authorization", "Bearer " + accessToken) - .param("latitude", 잠실역_교보문고_좌표.getLatitude()) - .param("longitude", 잠실역_교보문고_좌표.getLongitude()) - .when() - .get("/letters/nearby") - .then().log().all() - .statusCode(HttpStatus.OK.value()) - .extract(); - + final ExtractableResponse extract = RestAssured + .given().log().all() + .header("Authorization", authorizationForBearer(player)) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .param("latitude", 잠실역_교보문고_좌표.getLatitude()) + .param("longitude", 잠실역_교보문고_좌표.getLongitude()) + .when() + .get("/letters/nearby") + .then().log().all() + .statusCode(HttpStatus.OK.value()) + .extract(); + // then final List actual = extract.as(new TypeRef<>() { }); final int statusCode = extract.statusCode(); final List expected = List.of(NearByLetterResponse.from(letter1)); - + assertSoftly(softly -> { softly.assertThat(statusCode).isEqualTo(HttpStatus.OK.value()); softly.assertThat(actual) @@ -128,43 +82,40 @@ protected void setUp() { .isEqualTo(expected); }); } - + @Test void 쪽지_식별자로_쪽지를_조회한다() { // given & when final Player player = playerBuilder.init() .build(); - + final Place destination = placeBuilder.init() .position(잠실_루터회관_정문_좌표) .build(); - + final Game game = gameBuilder.init() .place(destination) .player(player) .startPosition(잠실역_교보문고_좌표) .build(); - + final Letter letter = letterBuilder.init() .position(잠실_루터회관_정문_좌표) .build(); - - final AuthToken generate = authTokenGenerator.generate(player.getMember(), 1L, AuthType.KAKAO); - final String accessToken = generate.getAccessToken(); - + final ExtractableResponse extract = RestAssured .given().log().all() - .header("Authorization", "Bearer " + accessToken) + .header("Authorization", authorizationForBearer(player)) .when() .get("/letters/{letterId}", letter.getId()) .then().log().all() .extract(); - + // then final int statusCode = extract.statusCode(); final LetterResponse actual = extract.as(LetterResponse.class); final LetterResponse expected = LetterResponse.from(letter); - + assertSoftly(softAssertions -> { softAssertions.assertThat(statusCode).isEqualTo(HttpStatus.OK.value()); softAssertions.assertThat(actual) @@ -174,38 +125,35 @@ protected void setUp() { .isEqualTo(expected); }); } - + @Test void 쪽지_식별자로_쪽지를_조회시_잔행중_게임이_없으면_예외가_발생한다() { // given & when final Player player = playerBuilder.init() .build(); - + final Place destination = placeBuilder.init() .position(잠실_루터회관_정문_좌표) .build(); - + final Letter letter = letterBuilder.init() .position(잠실_루터회관_정문_좌표) .build(); - - final AuthToken generate = authTokenGenerator.generate(player.getMember(), 1L, AuthType.KAKAO); - final String accessToken = generate.getAccessToken(); - + final ExtractableResponse extract = RestAssured .given().log().all() - .header("Authorization", "Bearer " + accessToken) + .header("Authorization", authorizationForBearer(player)) .when() .get("/letters/{letterId}", letter.getId()) .then().log().all() .extract(); - + // then final int statusCode = extract.statusCode(); final ExceptionResponse actual = extract.as(ExceptionResponse.class); - + final ExceptionResponse expected = new ExceptionResponse(NOT_EXIST_IN_PROGRESS.errorCode(), NOT_EXIST_IN_PROGRESS.errorMessage()); - + assertSoftly(softAssertions -> { softAssertions.assertThat(statusCode).isEqualTo(HttpStatus.NOT_FOUND.value()); softAssertions.assertThat(actual) @@ -215,7 +163,7 @@ protected void setUp() { .isEqualTo(expected); }); } - + @Test void 쪽지_등록_요청시_쪽지를_등록한_플레이어가_존재하고_그_플레이어가_진행중인_게임이_있으면_정상적으로_쪽지를_생성한다() { //given @@ -224,26 +172,23 @@ protected void setUp() { final Game game = gameBuilder.init() .player(player) .build(); - - final AuthToken generate = authTokenGenerator.generate(player.getMember(), 1L, AuthType.KAKAO); - final String accessToken = generate.getAccessToken(); - + String message = "날씨가 선선하네요"; final LetterRequest letterRequest = new LetterRequest(message, - 잠실_루터회관_정문_좌표.getLatitude().doubleValue(), - 잠실_루터회관_정문_좌표.getLongitude().doubleValue()); - + 잠실_루터회관_정문_좌표.getLatitude().doubleValue(), + 잠실_루터회관_정문_좌표.getLongitude().doubleValue()); + //when final ExtractableResponse extract = RestAssured .given().log().all() - .header("Authorization", "Bearer " + accessToken) + .header("Authorization", authorizationForBearer(player)) .contentType(ContentType.JSON) .body(letterRequest) .when() .post("/letters") .then().log().all() .extract(); - + //then final int statusCode = extract.statusCode(); final String location = extract.header("Location"); @@ -256,42 +201,37 @@ protected void setUp() { message, null ); - + assertSoftly(softAssertions -> { - softAssertions.assertThat(statusCode).isEqualTo(HttpStatus.CREATED.value()); - softAssertions.assertThat(location).isNotEqualTo("/letters" + letterId); - softAssertions.assertThat(actual) - .usingRecursiveComparison() - .ignoringExpectedNullFields() - .isEqualTo(expected); - } - ); + softAssertions.assertThat(statusCode).isEqualTo(HttpStatus.CREATED.value()); + softAssertions.assertThat(location).isNotEqualTo("/letters" + letterId); + softAssertions.assertThat(actual) + .usingRecursiveComparison() + .ignoringExpectedNullFields() + .isEqualTo(expected); + } + ); } - + @Test void 쪽지_등록_요청시_쪽지를_등록한_플레이어가_존재하지_않으면_예외가_발생한다() { //given - final AuthToken generate = authTokenGenerator.generate(new Member(1L, "email", false), - 1L, - AuthType.KAKAO); - final String accessToken = generate.getAccessToken(); - String message = "날씨가 선선하네요"; final LetterRequest letterRequest = new LetterRequest(message, - 잠실_루터회관_정문_좌표.getLatitude().doubleValue(), - 잠실_루터회관_정문_좌표.getLongitude().doubleValue()); - + 잠실_루터회관_정문_좌표.getLatitude().doubleValue(), + 잠실_루터회관_정문_좌표.getLongitude().doubleValue()); + //when final ExtractableResponse extract = RestAssured .given().log().all() - .header("Authorization", "Bearer " + accessToken) + .header("Authorization", authorizationForBearer(new Member(1L, "email", false))) .contentType(ContentType.JSON) .body(letterRequest) .when() .post("/letters") .then().log().all() .extract(); - + //then final int statusCode = extract.statusCode(); final ExceptionResponse actual = extract.as(ExceptionResponse.class); @@ -299,16 +239,16 @@ protected void setUp() { PLAYER_NOT_FOUND.errorCode(), PLAYER_NOT_FOUND.errorMessage() ); - + assertSoftly(softAssertions -> { - softAssertions.assertThat(statusCode).isEqualTo(HttpStatus.NOT_FOUND.value()); - softAssertions.assertThat(actual) - .usingRecursiveComparison() - .isEqualTo(expected); - } - ); + softAssertions.assertThat(statusCode).isEqualTo(HttpStatus.NOT_FOUND.value()); + softAssertions.assertThat(actual) + .usingRecursiveComparison() + .isEqualTo(expected); + } + ); } - + @Test void 쪽지_등록_요청시_쪽지를_등록한_진행중인_게임이_존재하지_않으면_예외가_발생한다() { //given @@ -318,27 +258,23 @@ protected void setUp() { .player(player) .gameStatus(DONE) .build(); - final AuthToken generate = authTokenGenerator.generate(player.getMember(), - 1L, - AuthType.KAKAO); - final String accessToken = generate.getAccessToken(); - + String message = "날씨가 선선하네요"; final LetterRequest letterRequest = new LetterRequest(message, - 잠실_루터회관_정문_좌표.getLatitude().doubleValue(), - 잠실_루터회관_정문_좌표.getLongitude().doubleValue()); - + 잠실_루터회관_정문_좌표.getLatitude().doubleValue(), + 잠실_루터회관_정문_좌표.getLongitude().doubleValue()); + //when final ExtractableResponse extract = RestAssured .given().log().all() - .header("Authorization", "Bearer " + accessToken) + .header("Authorization", authorizationForBearer(player)) .contentType(ContentType.JSON) .body(letterRequest) .when() .post("/letters") .then().log().all() .extract(); - + //then final int statusCode = extract.statusCode(); final ExceptionResponse actual = extract.as(ExceptionResponse.class); @@ -346,58 +282,55 @@ protected void setUp() { NOT_EXIST_IN_PROGRESS.errorCode(), NOT_EXIST_IN_PROGRESS.errorMessage() ); - + assertSoftly(softAssertions -> { - softAssertions.assertThat(statusCode).isEqualTo(HttpStatus.NOT_FOUND.value()); - softAssertions.assertThat(actual) - .usingRecursiveComparison() - .isEqualTo(expected); - } - ); + softAssertions.assertThat(statusCode).isEqualTo(HttpStatus.NOT_FOUND.value()); + softAssertions.assertThat(actual) + .usingRecursiveComparison() + .isEqualTo(expected); + } + ); } @Test void 게임아이디와_회원으로_읽은쪽지로그를_모두_조회한다() { // given & when final Player player = playerBuilder.init() - .build(); + .build(); final Place destination = placeBuilder.init() - .position(잠실_루터회관_정문_좌표) - .build(); + .position(잠실_루터회관_정문_좌표) + .build(); final Game game1 = gameBuilder.init() - .place(destination) - .player(player) - .startPosition(잠실_루터회관_정문_좌표) - .build(); + .place(destination) + .player(player) + .startPosition(잠실_루터회관_정문_좌표) + .build(); final Game game2 = gameBuilder.init() - .place(destination) - .player(player) - .startPosition(역삼역_좌표) - .build(); + .place(destination) + .player(player) + .startPosition(역삼역_좌표) + .build(); final Letter letter = letterBuilder.init() - .position(잠실_루터회관_정문_좌표) - .build(); + .position(잠실_루터회관_정문_좌표) + .build(); final ReadLetterLog readLetterLog1 = readLetterLogBuilder.init() - .game(game1) - .letter(letter) - .build(); + .game(game1) + .letter(letter) + .build(); final ReadLetterLog readLetterLog2 = readLetterLogBuilder.init() - .game(game2) - .letter(letter) - .build(); - - final AuthToken generate = authTokenGenerator.generate(player.getMember(), 1L, AuthType.KAKAO); - final String accessToken = generate.getAccessToken(); + .game(game2) + .letter(letter) + .build(); final ExtractableResponse extract = RestAssured .given().log().all() - .header("Authorization", "Bearer " + accessToken) + .header("Authorization", authorizationForBearer(player)) .param("gameId", game1.getId()) .param("logType", "READ") .when() @@ -415,10 +348,10 @@ protected void setUp() { assertSoftly(softly -> { softly.assertThat(statusCode).isEqualTo(HttpStatus.OK.value()); softly.assertThat(actual) - .hasSize(1) - .usingRecursiveComparison() - .ignoringFields("registerDate") - .isEqualTo(expected); + .hasSize(1) + .usingRecursiveComparison() + .ignoringFields("registerDate") + .isEqualTo(expected); }); } @@ -427,33 +360,30 @@ protected void setUp() { 게임아이디와_회원으로_작성한_쪽지로그를_모두_조회한다() { // given & when final Player player = playerBuilder.init() - .build(); + .build(); final Place destination = placeBuilder.init() - .position(잠실_루터회관_정문_좌표) - .build(); + .position(잠실_루터회관_정문_좌표) + .build(); final Game game = gameBuilder.init() - .place(destination) - .player(player) - .startPosition(잠실_루터회관_정문_좌표) - .build(); + .place(destination) + .player(player) + .startPosition(잠실_루터회관_정문_좌표) + .build(); final Letter letter = letterBuilder.init() - .position(잠실_루터회관_정문_좌표) - .build(); + .position(잠실_루터회관_정문_좌표) + .build(); final WriteLetterLog writeLetterLog1 = writeLetterLogBuilder.init() - .game(game) - .letter(letter) - .build(); - - final AuthToken generate = authTokenGenerator.generate(player.getMember(), 1L, AuthType.KAKAO); - final String accessToken = generate.getAccessToken(); + .game(game) + .letter(letter) + .build(); final ExtractableResponse extract = RestAssured .given().log().all() - .header("Authorization", "Bearer " + accessToken) + .header("Authorization", authorizationForBearer(player)) .param("gameId", game.getId()) .param("logType", "WRITE") .when() @@ -471,10 +401,10 @@ protected void setUp() { assertSoftly(softly -> { softly.assertThat(statusCode).isEqualTo(HttpStatus.OK.value()); softly.assertThat(actual) - .hasSize(1) - .usingRecursiveComparison() - .ignoringFields("registerDate") - .isEqualTo(expected); + .hasSize(1) + .usingRecursiveComparison() + .ignoringFields("registerDate") + .isEqualTo(expected); }); } @@ -482,48 +412,45 @@ protected void setUp() { void 쪽지로그_조회시_잘못된_파라미터는_예외를_던진다() { // given & when final Player player = playerBuilder.init() - .build(); + .build(); final Place destination = placeBuilder.init() - .position(잠실_루터회관_정문_좌표) - .build(); + .position(잠실_루터회관_정문_좌표) + .build(); final Game game1 = gameBuilder.init() - .place(destination) - .player(player) - .startPosition(잠실_루터회관_정문_좌표) - .build(); + .place(destination) + .player(player) + .startPosition(잠실_루터회관_정문_좌표) + .build(); final Game game2 = gameBuilder.init() - .place(destination) - .player(player) - .startPosition(역삼역_좌표) - .build(); + .place(destination) + .player(player) + .startPosition(역삼역_좌표) + .build(); final Letter letter = letterBuilder.init() - .position(잠실_루터회관_정문_좌표) - .build(); + .position(잠실_루터회관_정문_좌표) + .build(); final Letter letter2 = letterBuilder.init() - .position(GS25_방이도곡점_좌표) - .build(); + .position(GS25_방이도곡점_좌표) + .build(); final WriteLetterLog writeLetterLog1 = writeLetterLogBuilder.init() - .game(game1) - .letter(letter) - .build(); + .game(game1) + .letter(letter) + .build(); final WriteLetterLog writeLetterLog2 = writeLetterLogBuilder.init() - .game(game2) - .letter(letter2) - .build(); - - final AuthToken generate = authTokenGenerator.generate(player.getMember(), 1L, AuthType.KAKAO); - final String accessToken = generate.getAccessToken(); + .game(game2) + .letter(letter2) + .build(); final ExtractableResponse extract = RestAssured .given().log().all() - .header("Authorization", "Bearer " + accessToken) + .header("Authorization", authorizationForBearer(player)) .param("gameId", game1.getId()) .param("logType", "잘못된enum") .when() @@ -537,15 +464,15 @@ protected void setUp() { final ExceptionResponse expected = new ExceptionResponse(INVALID_REQUEST_PARAMETERS.errorCode(), INVALID_REQUEST_PARAMETERS.errorMessage()); assertSoftly(softAssertions -> { - softAssertions.assertThat(statusCode).isEqualTo(HttpStatus.BAD_REQUEST.value()); - softAssertions.assertThat(actual) - .usingRecursiveComparison() - .ignoringExpectedNullFields() - .ignoringFieldsOfTypes(LocalDateTime.class) - .ignoringFields("registerDate") - .isEqualTo(expected); - } - ); + softAssertions.assertThat(statusCode).isEqualTo(HttpStatus.BAD_REQUEST.value()); + softAssertions.assertThat(actual) + .usingRecursiveComparison() + .ignoringExpectedNullFields() + .ignoringFieldsOfTypes(LocalDateTime.class) + .ignoringFields("registerDate") + .isEqualTo(expected); + } + ); } @@ -559,17 +486,14 @@ protected void setUp() { .player(player) .build(); - final AuthToken generate = authTokenGenerator.generate(player.getMember(), 1L, AuthType.KAKAO); - final String accessToken = generate.getAccessToken(); - final LetterRequest letterRequest = new LetterRequest(message, - 잠실_루터회관_정문_좌표.getLatitude().doubleValue(), - 잠실_루터회관_정문_좌표.getLongitude().doubleValue()); + 잠실_루터회관_정문_좌표.getLatitude().doubleValue(), + 잠실_루터회관_정문_좌표.getLongitude().doubleValue()); //when final ExtractableResponse extract = RestAssured .given().log().all() - .header("Authorization", "Bearer " + accessToken) + .header("Authorization", authorizationForBearer(player)) .contentType(ContentType.JSON) .body(letterRequest) .when() @@ -586,11 +510,11 @@ protected void setUp() { ); assertSoftly(softAssertions -> { - softAssertions.assertThat(statusCode).isEqualTo(HttpStatus.BAD_REQUEST.value()); - softAssertions.assertThat(actual) - .usingRecursiveComparison() - .isEqualTo(expected); - } - ); + softAssertions.assertThat(statusCode).isEqualTo(HttpStatus.BAD_REQUEST.value()); + softAssertions.assertThat(actual) + .usingRecursiveComparison() + .isEqualTo(expected); + } + ); } } diff --git a/backend/src/test/java/com/now/naaga/like/application/PlaceLikeServiceTest.java b/backend/src/test/java/com/now/naaga/like/application/PlaceLikeServiceTest.java index f7266a748..d1ca8085e 100644 --- a/backend/src/test/java/com/now/naaga/like/application/PlaceLikeServiceTest.java +++ b/backend/src/test/java/com/now/naaga/like/application/PlaceLikeServiceTest.java @@ -5,10 +5,7 @@ import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertThrows; -import com.now.naaga.common.builder.PlaceBuilder; -import com.now.naaga.common.builder.PlaceLikeBuilder; -import com.now.naaga.common.builder.PlaceStatisticsBuilder; -import com.now.naaga.common.builder.PlayerBuilder; +import com.now.naaga.common.ServiceTest; import com.now.naaga.common.exception.BaseExceptionType; import com.now.naaga.like.application.dto.ApplyLikeCommand; import com.now.naaga.like.application.dto.CancelLikeCommand; @@ -19,59 +16,20 @@ import com.now.naaga.like.domain.PlaceLikeType; import com.now.naaga.like.exception.PlaceLikeException; import com.now.naaga.like.exception.PlaceLikeExceptionType; -import com.now.naaga.like.repository.PlaceLikeRepository; import com.now.naaga.place.domain.Place; import com.now.naaga.place.domain.PlaceStatistics; -import com.now.naaga.place.repository.PlaceStatisticsRepository; import com.now.naaga.player.domain.Player; import java.util.Optional; import org.assertj.core.api.SoftAssertions; -import org.junit.jupiter.api.DisplayNameGeneration; -import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.jdbc.Sql; import org.springframework.transaction.annotation.Transactional; @SuppressWarnings("NonAsciiCharacters") -@DisplayNameGeneration(ReplaceUnderscores.class) -@Sql("/truncate.sql") -@ActiveProfiles("test") -@SpringBootTest -class PlaceLikeServiceTest { - - private final PlaceLikeService placeLikeService; - - private final PlaceBuilder placeBuilder; - - private final PlayerBuilder playerBuilder; - - private final PlaceLikeBuilder placeLikeBuilder; - - private final PlaceStatisticsBuilder placeStatisticsBuilder; - - private final PlaceLikeRepository placeLikeRepository; - - private final PlaceStatisticsRepository placeStatisticsRepository; +class PlaceLikeServiceTest extends ServiceTest { @Autowired - public PlaceLikeServiceTest(final PlaceLikeService placeLikeService, - final PlaceBuilder placeBuilder, - final PlayerBuilder playerBuilder, - final PlaceLikeBuilder placeLikeBuilder, - final PlaceStatisticsBuilder placeStatisticsBuilder, - final PlaceLikeRepository placeLikeRepository, - final PlaceStatisticsRepository placeStatisticsRepository) { - this.placeLikeService = placeLikeService; - this.placeBuilder = placeBuilder; - this.playerBuilder = playerBuilder; - this.placeLikeBuilder = placeLikeBuilder; - this.placeStatisticsBuilder = placeStatisticsBuilder; - this.placeLikeRepository = placeLikeRepository; - this.placeStatisticsRepository = placeStatisticsRepository; - } + private PlaceLikeService placeLikeService; @Transactional @Test @@ -255,19 +213,19 @@ public PlaceLikeServiceTest(final PlaceLikeService placeLikeService, void 좋아요를_삭제하고_통계에서_좋아요를_1개_뺸다() { // given final Place place = placeBuilder.init() - .build(); + .build(); final Player player = playerBuilder.init() - .build(); + .build(); final PlaceLike placeLike = placeLikeBuilder.init() - .place(place) - .player(player) - .placeLikeType(PlaceLikeType.LIKE) - .build(); + .place(place) + .player(player) + .placeLikeType(PlaceLikeType.LIKE) + .build(); final long beforeLikeCount = 10L; placeStatisticsBuilder.init() - .place(place) - .likeCount(beforeLikeCount) - .build(); + .place(place) + .likeCount(beforeLikeCount) + .build(); final CancelLikeCommand cancelLikeCommand = new CancelLikeCommand(player.getId(), place.getId()); // when @@ -286,19 +244,19 @@ public PlaceLikeServiceTest(final PlaceLikeService placeLikeService, void 싫어요를_삭제하면_통계가_줄어들지_않는다() { // given final Place place = placeBuilder.init() - .build(); + .build(); final Player player = playerBuilder.init() - .build(); + .build(); final PlaceLike placeLike = placeLikeBuilder.init() - .place(place) - .player(player) - .placeLikeType(PlaceLikeType.DISLIKE) - .build(); + .place(place) + .player(player) + .placeLikeType(PlaceLikeType.DISLIKE) + .build(); final long beforeLikeCount = 10L; placeStatisticsBuilder.init() - .place(place) - .likeCount(beforeLikeCount) - .build(); + .place(place) + .likeCount(beforeLikeCount) + .build(); final CancelLikeCommand cancelLikeCommand = new CancelLikeCommand(player.getId(), place.getId()); // when @@ -317,19 +275,19 @@ public PlaceLikeServiceTest(final PlaceLikeService placeLikeService, void 좋아요가_0개일_때_좋아요를_삭제하면_통계에서_좋아요를_0개로_유지한다() { // given final Place place = placeBuilder.init() - .build(); + .build(); final Player player = playerBuilder.init() - .build(); + .build(); final PlaceLike placeLike = placeLikeBuilder.init() - .place(place) - .player(player) - .placeLikeType(PlaceLikeType.LIKE) - .build(); + .place(place) + .player(player) + .placeLikeType(PlaceLikeType.LIKE) + .build(); final long beforeLikeCount = 0L; placeStatisticsBuilder.init() - .place(place) - .likeCount(beforeLikeCount) - .build(); + .place(place) + .likeCount(beforeLikeCount) + .build(); final CancelLikeCommand cancelLikeCommand = new CancelLikeCommand(player.getId(), place.getId()); // when @@ -348,9 +306,9 @@ public PlaceLikeServiceTest(final PlaceLikeService placeLikeService, void 좋아요를_삭제할_때_좋아요가_존재하지_않으면_아무_일도_일어나지_않는다() { // given final Place place = placeBuilder.init() - .build(); + .build(); final Player player = playerBuilder.init() - .build(); + .build(); final CancelLikeCommand cancelLikeCommand = new CancelLikeCommand(player.getId(), place.getId()); // when & then @@ -362,8 +320,8 @@ public PlaceLikeServiceTest(final PlaceLikeService placeLikeService, //given final Long expected = 123L; final PlaceStatistics placeStatistics = placeStatisticsBuilder.init() - .likeCount(expected) - .build(); + .likeCount(expected) + .build(); final Long placeId = placeStatistics.getPlace().getId(); // when diff --git a/backend/src/test/java/com/now/naaga/like/domain/PlaceLikeTest.java b/backend/src/test/java/com/now/naaga/like/domain/PlaceLikeTest.java index d92a62d89..c13ade1db 100644 --- a/backend/src/test/java/com/now/naaga/like/domain/PlaceLikeTest.java +++ b/backend/src/test/java/com/now/naaga/like/domain/PlaceLikeTest.java @@ -16,7 +16,6 @@ import org.junit.jupiter.api.Test; import org.springframework.test.context.ActiveProfiles; -@ActiveProfiles("test") @SuppressWarnings("NonAsciiCharacters") @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) class PlaceLikeTest { diff --git a/backend/src/test/java/com/now/naaga/like/presentation/PlaceLikeControllerTest.java b/backend/src/test/java/com/now/naaga/like/presentation/PlaceLikeControllerTest.java index 88fd6c672..abe0eacb6 100644 --- a/backend/src/test/java/com/now/naaga/like/presentation/PlaceLikeControllerTest.java +++ b/backend/src/test/java/com/now/naaga/like/presentation/PlaceLikeControllerTest.java @@ -7,14 +7,7 @@ import static org.springframework.http.HttpStatus.NO_CONTENT; import static org.springframework.http.HttpStatus.OK; -import com.now.naaga.auth.domain.AuthToken; -import com.now.naaga.auth.infrastructure.AuthType; -import com.now.naaga.auth.infrastructure.jwt.AuthTokenGenerator; -import com.now.naaga.common.CommonControllerTest; -import com.now.naaga.common.builder.PlaceBuilder; -import com.now.naaga.common.builder.PlaceLikeBuilder; -import com.now.naaga.common.builder.PlaceStatisticsBuilder; -import com.now.naaga.common.builder.PlayerBuilder; +import com.now.naaga.common.ControllerTest; import com.now.naaga.common.exception.ExceptionResponse; import com.now.naaga.like.domain.MyPlaceLikeType; import com.now.naaga.like.domain.PlaceLike; @@ -23,7 +16,6 @@ import com.now.naaga.like.presentation.dto.CheckMyPlaceLikeResponse; import com.now.naaga.like.presentation.dto.PlaceLikeCountResponse; import com.now.naaga.like.presentation.dto.PlaceLikeResponse; -import com.now.naaga.member.domain.Member; import com.now.naaga.place.domain.Place; import com.now.naaga.place.domain.PlaceStatistics; import com.now.naaga.place.exception.PlaceStatisticsExceptionType; @@ -32,38 +24,13 @@ import io.restassured.http.ContentType; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayNameGeneration; -import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; @SuppressWarnings("NonAsciiCharacters") -@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) -class PlaceLikeControllerTest extends CommonControllerTest { - - @Autowired - private PlayerBuilder playerBuilder; - - @Autowired - private PlaceBuilder placeBuilder; - - @Autowired - private PlaceLikeBuilder placeLikeBuilder; - - @Autowired - private PlaceStatisticsBuilder placeStatisticsBuilder; - - @Autowired - private AuthTokenGenerator authTokenGenerator; - - @BeforeEach - void setup() { - super.setUp(); - } +class PlaceLikeControllerTest extends ControllerTest { @Test void 좋아요_등록이_성공하면_201_응답을_반환한다() { @@ -80,14 +47,10 @@ void setup() { final ApplyPlaceLikeRequest applyPlaceLikeRequest = new ApplyPlaceLikeRequest(PlaceLikeType.LIKE); - final Member member = player.getMember(); - final AuthToken generate = authTokenGenerator.generate(member, member.getId(), AuthType.KAKAO); - final String accessToken = generate.getAccessToken(); - // when final ExtractableResponse extract = RestAssured .given().log().all() - .header("Authorization", "Bearer " + accessToken) + .header("Authorization", authorizationForBearer(player)) .contentType(MediaType.APPLICATION_JSON_VALUE) .body(applyPlaceLikeRequest) .when() @@ -131,14 +94,10 @@ void setup() { final ApplyPlaceLikeRequest applyPlaceLikeRequest = new ApplyPlaceLikeRequest(PlaceLikeType.LIKE); - final Member member = player.getMember(); - final AuthToken generate = authTokenGenerator.generate(member, member.getId(), AuthType.KAKAO); - final String accessToken = generate.getAccessToken(); - // when final ExtractableResponse extract = RestAssured .given().log().all() - .header("Authorization", "Bearer " + accessToken) + .header("Authorization", authorizationForBearer(player)) .contentType(MediaType.APPLICATION_JSON_VALUE) .body(applyPlaceLikeRequest) .when() @@ -162,21 +121,18 @@ void setup() { void 좋아요_삭제를_성공하면_204응답을_한다() { //given final Place place = placeBuilder.init() - .build(); + .build(); final PlaceLike placeLike = placeLikeBuilder.init() - .place(place) - .build(); + .place(place) + .build(); placeStatisticsBuilder.init() - .place(place) - .build(); - final Member member = placeLike.getPlayer().getMember(); - final AuthToken generate = authTokenGenerator.generate(member, member.getId(), AuthType.KAKAO); - final String accessToken = generate.getAccessToken(); + .place(place) + .build(); //when final ExtractableResponse extract = RestAssured .given().log().all() - .header("Authorization", "Bearer " + accessToken) + .header("Authorization", authorizationForBearer(placeLike.getPlayer())) .contentType(ContentType.JSON) .pathParam("placeId", place.getId()) .when() @@ -206,14 +162,10 @@ void setup() { .placeLikeType(myType) .build(); - final Member member = player.getMember(); - final AuthToken generate = authTokenGenerator.generate(member, member.getId(), AuthType.KAKAO); - final String accessToken = generate.getAccessToken(); - // when final ExtractableResponse extract = RestAssured .given().log().all() - .header("Authorization", "Bearer " + accessToken) + .header("Authorization", authorizationForBearer(player)) .contentType(MediaType.APPLICATION_JSON_VALUE) .when() .get("/places/{placeId}/likes/my", place.getId()) @@ -240,14 +192,10 @@ void setup() { final Place place = placeBuilder.init() .build(); - final Member member = player.getMember(); - final AuthToken generate = authTokenGenerator.generate(member, member.getId(), AuthType.KAKAO); - final String accessToken = generate.getAccessToken(); - // when final ExtractableResponse extract = RestAssured .given().log().all() - .header("Authorization", "Bearer " + accessToken) + .header("Authorization", authorizationForBearer(player)) .contentType(MediaType.APPLICATION_JSON_VALUE) .when() .get("/places/{placeId}/likes/my", place.getId()) diff --git a/backend/src/test/java/com/now/naaga/member/persistence/repository/MemberRepositoryTest.java b/backend/src/test/java/com/now/naaga/member/persistence/repository/MemberRepositoryTest.java index 2892f6d67..0599e2af4 100644 --- a/backend/src/test/java/com/now/naaga/member/persistence/repository/MemberRepositoryTest.java +++ b/backend/src/test/java/com/now/naaga/member/persistence/repository/MemberRepositoryTest.java @@ -2,26 +2,15 @@ import static org.assertj.core.api.Assertions.assertThat; +import com.now.naaga.common.AbstractTest; import com.now.naaga.member.domain.Member; -import org.junit.jupiter.api.DisplayNameGeneration; -import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.jdbc.Sql; -import org.springframework.transaction.annotation.Transactional; -@ActiveProfiles("test") @SuppressWarnings("NonAsciiCharacters") -@Sql("/truncate.sql") -@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) -@Transactional @SpringBootTest -class MemberRepositoryTest { - - @Autowired - private MemberRepository memberRepository; +class MemberRepositoryTest extends AbstractTest { @Test void 이메일로_회원을_조회한다() { diff --git a/backend/src/test/java/com/now/naaga/place/application/PlaceServiceTest.java b/backend/src/test/java/com/now/naaga/place/application/PlaceServiceTest.java index 43909470e..625643f3d 100644 --- a/backend/src/test/java/com/now/naaga/place/application/PlaceServiceTest.java +++ b/backend/src/test/java/com/now/naaga/place/application/PlaceServiceTest.java @@ -1,11 +1,13 @@ package com.now.naaga.place.application; -import com.now.naaga.common.builder.PlaceBuilder; -import com.now.naaga.common.builder.PlayerBuilder; -import com.now.naaga.common.builder.TemporaryPlaceBuilder; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.SoftAssertions.assertSoftly; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import com.now.naaga.common.ServiceTest; import com.now.naaga.common.exception.BaseExceptionType; import com.now.naaga.common.fixture.PositionFixture; -import com.now.naaga.common.infrastructure.AwsS3FileManager; import com.now.naaga.place.application.dto.CreatePlaceCommand; import com.now.naaga.place.application.dto.RecommendPlaceCommand; import com.now.naaga.place.domain.Place; @@ -13,120 +15,86 @@ import com.now.naaga.place.domain.Position; import com.now.naaga.place.exception.PlaceException; import com.now.naaga.place.exception.PlaceExceptionType; -import com.now.naaga.place.repository.PlaceStatisticsRepository; import com.now.naaga.player.domain.Player; import com.now.naaga.temporaryplace.domain.TemporaryPlace; -import com.now.naaga.temporaryplace.repository.TemporaryPlaceRepository; -import org.junit.jupiter.api.DisplayNameGeneration; -import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; +import java.util.Optional; import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.jdbc.Sql; import org.springframework.transaction.annotation.Transactional; -import java.util.Optional; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.SoftAssertions.assertSoftly; -import static org.junit.jupiter.api.Assertions.assertAll; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.*; - @SuppressWarnings("NonAsciiCharacters") -@DisplayNameGeneration(ReplaceUnderscores.class) -@Sql("/truncate.sql") -@ActiveProfiles("test") -@SpringBootTest -class PlaceServiceTest { - - @Autowired - private TemporaryPlaceRepository temporaryPlaceRepository; - - @Autowired - private PlaceStatisticsRepository placeStatisticsRepository; - +class PlaceServiceTest extends ServiceTest { + @Autowired private PlaceService placeService; - - @Autowired - private TemporaryPlaceBuilder temporaryPlaceBuilder; - - @Autowired - private PlayerBuilder playerBuilder; - @Autowired - private PlaceBuilder placeBuilder; - @Transactional @Test void 장소를_등록한_뒤_기존의_검수_장소_데이터는_삭제한다() { // given final Player player = playerBuilder.init() .build(); - + final TemporaryPlace temporaryPlace = temporaryPlaceBuilder.init() .build(); - + final Long temporaryPlaceId = temporaryPlace.getId(); - + final CreatePlaceCommand createPlaceCommand = new CreatePlaceCommand("루터회관", - "이곳은 루터회관이다 알겠냐", - Position.of(1.23, 4.56), - "image/url", - player.getId(), - temporaryPlaceId); - + "이곳은 루터회관이다 알겠냐", + Position.of(1.23, 4.56), + "image/url", + player.getId(), + temporaryPlaceId); + // when final Place actual = placeService.createPlace(createPlaceCommand); - + // then final Place expected = new Place(createPlaceCommand.name(), - createPlaceCommand.description(), - createPlaceCommand.position(), - createPlaceCommand.imageUrl(), - player); - + createPlaceCommand.description(), + createPlaceCommand.position(), + createPlaceCommand.imageUrl(), + player); + final TemporaryPlace found = temporaryPlaceRepository.findById(temporaryPlaceId) .orElse(null); - + assertAll( () -> assertThat(actual).usingRecursiveComparison() .ignoringExpectedNullFields() .isEqualTo(expected), () -> assertThat(found).isNull() - ); + ); } - + @Test void 장소_등록_시_장소_통계도_함께_등록된다() { // given final Player player = playerBuilder.init() .build(); - + final TemporaryPlace temporaryPlace = temporaryPlaceBuilder.init() .build(); - + final Long temporaryPlaceId = temporaryPlace.getId(); - + final CreatePlaceCommand createPlaceCommand = new CreatePlaceCommand("루터회관", - "이곳은 루터회관이다 알겠냐", - Position.of(1.23, 4.56), - "image/url", - player.getId(), - temporaryPlaceId); - + "이곳은 루터회관이다 알겠냐", + Position.of(1.23, 4.56), + "image/url", + player.getId(), + temporaryPlaceId); + // when final Place place = placeService.createPlace(createPlaceCommand); - + // then final Optional placeStatistics = placeStatisticsRepository.findByPlaceId(place.getId()); assertAll( () -> assertThat(placeStatistics).isNotEmpty() - ); + ); } @Transactional @@ -140,14 +108,14 @@ class PlaceServiceTest { final Position 제주좌표 = PositionFixture.제주_좌표; final Place 잠실역교보문고 = placeBuilder.init() - .position(잠실역교보문고좌표) - .build(); + .position(잠실역교보문고좌표) + .build(); final Place 잠실루터회관정문 = placeBuilder.init() - .position(잠실루터회관정문좌표) - .build(); + .position(잠실루터회관정문좌표) + .build(); final Place 제주 = placeBuilder.init() - .position(제주좌표) - .build(); + .position(제주좌표) + .build(); final RecommendPlaceCommand recommendPlaceCommand = new RecommendPlaceCommand(현재위치); @@ -170,11 +138,11 @@ class PlaceServiceTest { final Position 잠실루터회관정문좌표 = PositionFixture.잠실_루터회관_정문_좌표; final Place 잠실역교보문고 = placeBuilder.init() - .position(잠실역교보문고좌표) - .build(); + .position(잠실역교보문고좌표) + .build(); final Place 잠실루터회관정문 = placeBuilder.init() - .position(잠실루터회관정문좌표) - .build(); + .position(잠실루터회관정문좌표) + .build(); final RecommendPlaceCommand recommendPlaceCommand = new RecommendPlaceCommand(제주좌표); diff --git a/backend/src/test/java/com/now/naaga/place/application/PlaceStatisticsServiceTest.java b/backend/src/test/java/com/now/naaga/place/application/PlaceStatisticsServiceTest.java index c9e8b5692..b23e91476 100644 --- a/backend/src/test/java/com/now/naaga/place/application/PlaceStatisticsServiceTest.java +++ b/backend/src/test/java/com/now/naaga/place/application/PlaceStatisticsServiceTest.java @@ -4,8 +4,7 @@ import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertThrows; -import com.now.naaga.common.builder.PlaceBuilder; -import com.now.naaga.common.builder.PlaceStatisticsBuilder; +import com.now.naaga.common.ServiceTest; import com.now.naaga.common.exception.BaseExceptionType; import com.now.naaga.place.application.dto.CreatePlaceStatisticsCommand; import com.now.naaga.place.application.dto.FindPlaceStatisticsByPlaceIdCommand; @@ -17,35 +16,16 @@ import com.now.naaga.place.exception.PlaceExceptionType; import com.now.naaga.place.exception.PlaceStatisticsException; import com.now.naaga.place.exception.PlaceStatisticsExceptionType; -import com.now.naaga.place.repository.PlaceStatisticsRepository; -import org.junit.jupiter.api.DisplayNameGeneration; -import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.jdbc.Sql; import org.springframework.transaction.annotation.Transactional; @SuppressWarnings("NonAsciiCharacters") -@DisplayNameGeneration(ReplaceUnderscores.class) -@Sql("/truncate.sql") -@ActiveProfiles("test") -@SpringBootTest -class PlaceStatisticsServiceTest { - - @Autowired - private PlaceStatisticsRepository placeStatisticsRepository; +class PlaceStatisticsServiceTest extends ServiceTest { @Autowired private PlaceStatisticsService placeStatisticsService; - @Autowired - private PlaceStatisticsBuilder placeStatisticsBuilder; - - @Autowired - private PlaceBuilder placeBuilder; - @Transactional @Test void 장소통계를_생성한다() { diff --git a/backend/src/test/java/com/now/naaga/place/domain/PlaceStatisticsTest.java b/backend/src/test/java/com/now/naaga/place/domain/PlaceStatisticsTest.java index 59dd74f95..21a6334d8 100644 --- a/backend/src/test/java/com/now/naaga/place/domain/PlaceStatisticsTest.java +++ b/backend/src/test/java/com/now/naaga/place/domain/PlaceStatisticsTest.java @@ -10,7 +10,6 @@ @SuppressWarnings("NonAsciiCharacters") @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) -@ActiveProfiles("test") class PlaceStatisticsTest { @Test diff --git a/backend/src/test/java/com/now/naaga/place/presentation/PlaceControllerTest.java b/backend/src/test/java/com/now/naaga/place/presentation/PlaceControllerTest.java index 6643490bc..2c787308d 100644 --- a/backend/src/test/java/com/now/naaga/place/presentation/PlaceControllerTest.java +++ b/backend/src/test/java/com/now/naaga/place/presentation/PlaceControllerTest.java @@ -1,49 +1,23 @@ package com.now.naaga.place.presentation; -import static io.restassured.RestAssured.given; import static org.assertj.core.api.SoftAssertions.assertSoftly; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; -import com.now.naaga.auth.domain.AuthToken; -import com.now.naaga.auth.infrastructure.AuthType; -import com.now.naaga.auth.infrastructure.jwt.AuthTokenGenerator; -import com.now.naaga.common.CommonControllerTest; -import com.now.naaga.common.builder.PlaceBuilder; -import com.now.naaga.common.builder.PlayerBuilder; +import com.now.naaga.common.ControllerTest; import com.now.naaga.place.domain.Place; -import com.now.naaga.place.domain.Position; -import com.now.naaga.place.presentation.dto.CoordinateResponse; -import com.now.naaga.place.presentation.dto.CreatePlaceRequest; import com.now.naaga.place.presentation.dto.PlaceResponse; -import com.now.naaga.player.domain.Player; +import io.restassured.RestAssured; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; import java.util.List; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayNameGeneration; -import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.test.context.ActiveProfiles; @SuppressWarnings("NonAsciiCharacters") -@DisplayNameGeneration(ReplaceUnderscores.class) -@ActiveProfiles("test") -public class PlaceControllerTest extends CommonControllerTest { - - @Autowired - private AuthTokenGenerator authTokenGenerator; - - @Autowired - private PlayerBuilder playerBuilder; - - @Autowired - private PlaceBuilder placeBuilder; +public class PlaceControllerTest extends ControllerTest { @Value("${manager.id}") private String id; @@ -51,11 +25,6 @@ public class PlaceControllerTest extends CommonControllerTest { @Value("${manager.password}") private String password; - @BeforeEach - protected void setUp() { - super.setUp(); - } - // @Test // void 장소_등록_요청이_성공하면_201_상태코드와_생성된_장소를_응답한다() { // // given @@ -105,14 +74,11 @@ protected void setUp() { //given final Place place = placeBuilder.init() .build(); - - final AuthToken generate = authTokenGenerator.generate(place.getRegisteredPlayer().getMember(), 1L, AuthType.KAKAO); - final String accessToken = generate.getAccessToken(); //when - final ExtractableResponse extract = given() - .log().all() + final ExtractableResponse extract = RestAssured + .given().log().all() + .header("Authorization", authorizationForBearer(place.getRegisteredPlayer())) .pathParam("placeId", place.getId()) - .header("Authorization", "Bearer " + accessToken) .when() .get("/places/{placeId}") .then() @@ -136,13 +102,10 @@ protected void setUp() { final Place place = placeBuilder.init() .build(); - final AuthToken generate = authTokenGenerator.generate(place.getRegisteredPlayer().getMember(), 1L, AuthType.KAKAO); - final String accessToken = generate.getAccessToken(); - //when - final ExtractableResponse extract = given() - .log().all() - .header("Authorization", "Bearer " + accessToken) + final ExtractableResponse extract = RestAssured + .given().log().all() + .header("Authorization", authorizationForBearer(place.getRegisteredPlayer())) .queryParam("sort-by", "time") .queryParam("order", "descending") .when() diff --git a/backend/src/test/java/com/now/naaga/player/application/PlayerServiceTest.java b/backend/src/test/java/com/now/naaga/player/application/PlayerServiceTest.java index c5a24b2e8..6c67990bf 100644 --- a/backend/src/test/java/com/now/naaga/player/application/PlayerServiceTest.java +++ b/backend/src/test/java/com/now/naaga/player/application/PlayerServiceTest.java @@ -1,47 +1,39 @@ package com.now.naaga.player.application; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.SoftAssertions.assertSoftly; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertThrows; -import com.now.naaga.common.builder.PlayerBuilder; +import com.now.naaga.common.ServiceTest; import com.now.naaga.member.domain.Member; -import com.now.naaga.member.persistence.repository.MemberRepository; import com.now.naaga.player.application.dto.AddScoreCommand; +import com.now.naaga.player.application.dto.EditPlayerNicknameCommand; import com.now.naaga.player.domain.Player; import com.now.naaga.player.domain.Rank; +import com.now.naaga.player.exception.PlayerException; +import com.now.naaga.player.exception.PlayerExceptionType; import com.now.naaga.player.persistence.repository.PlayerRepository; import com.now.naaga.player.presentation.dto.PlayerRequest; import com.now.naaga.score.domain.Score; import java.util.ArrayList; import java.util.List; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayNameGeneration; -import org.junit.jupiter.api.DisplayNameGenerator; -import org.junit.jupiter.api.Test; + +import org.assertj.core.api.SoftAssertions; +import org.junit.jupiter.api.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Profile; +import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.jdbc.Sql; import org.springframework.transaction.annotation.Transactional; - -@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) -@Transactional -@SpringBootTest -@Sql("/truncate.sql") -class PlayerServiceTest { +class PlayerServiceTest extends ServiceTest { @Autowired private PlayerService playerService; - @Autowired - private PlayerRepository playerRepository; - - @Autowired - private MemberRepository memberRepository; - - @Autowired - private PlayerBuilder playerBuilder; - private List playerList = new ArrayList<>(); @BeforeEach @@ -100,4 +92,32 @@ void setUp() { final Player afterPlayer = playerRepository.findById(player.getId()).get(); assertThat(afterPlayer.getTotalScore()).isEqualTo(beforeScore.plus(addedScore)); } + + @Test + void 플레이어의_닉네임을_변경한다() { + //given + final String expected = "변경 닉네임"; + final Player player = playerBuilder.init().build(); + final EditPlayerNicknameCommand editPlayerNicknameCommand = new EditPlayerNicknameCommand(player.getId(), expected); + + //when + final Player actual = playerService.editPlayerNickname(editPlayerNicknameCommand); + + //then + assertThat(actual.getNickname()).isEqualTo(expected); + } + + @Test + void 플레이어의_닉네임을_변경_시_불가능한_닉네임을_입력하면_예외를_발생한다() { + //given + final String expected = "변경 닉네임!!"; + final Player player = playerBuilder.init().build(); + final EditPlayerNicknameCommand editPlayerNicknameCommand = new EditPlayerNicknameCommand(player.getId(), expected); + + //when & then + assertAll(() -> { + final PlayerException playerException = assertThrows(PlayerException.class, () -> playerService.editPlayerNickname(editPlayerNicknameCommand)); + assertThat(playerException).usingRecursiveComparison().isEqualTo(new PlayerException(PlayerExceptionType.UNAVAILABLE_NICKNAME)); + }); + } } diff --git a/backend/src/test/java/com/now/naaga/player/domain/PlayerTest.java b/backend/src/test/java/com/now/naaga/player/domain/PlayerTest.java new file mode 100644 index 000000000..42b185c44 --- /dev/null +++ b/backend/src/test/java/com/now/naaga/player/domain/PlayerTest.java @@ -0,0 +1,108 @@ +package com.now.naaga.player.domain; + +import com.now.naaga.common.fixture.MemberFixture; +import com.now.naaga.common.fixture.PlayerFixture; +import com.now.naaga.member.domain.Member; +import com.now.naaga.player.exception.PlayerException; +import com.now.naaga.player.exception.PlayerExceptionType; +import com.now.naaga.score.domain.Score; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.*; + +@SuppressWarnings("NonAsciiCharacters") +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +class PlayerTest { + + @MethodSource("unavailableNicknames") + @ParameterizedTest + void 플레이어_생성_시_닉네임에_한글_영어_숫자_공백_이외의_문자를_입력하거나_문자가_2자부터_20자에서_벗어나면_예외를_발생한다(final String nickname) { + // given + final Member member = MemberFixture.MEMBER(); + final Score totalScore = new Score(100); + + // when & then + assertAll(() -> { + final PlayerException playerException = assertThrows(PlayerException.class, () -> new Player(nickname, totalScore, member)); + assertThat(playerException).usingRecursiveComparison().isEqualTo(new PlayerException(PlayerExceptionType.UNAVAILABLE_NICKNAME)); + }); + } + + @MethodSource("availableNicknames") + @ParameterizedTest + void 플레이어를_생성한다(final String nickname) { + // given + final Member member = MemberFixture.MEMBER(); + final Score totalScore = new Score(100); + + // when + final Player player = new Player(nickname, totalScore, member); + + // then + assertThat(player).isNotNull(); + } + + @MethodSource("unavailableNicknames") + @ParameterizedTest + void 플레이어_닉네임_변경_시_닉네임에_한글_영어_숫자_공백_이외의_문자를_입력하거나_문자가_2자부터_20자에서_벗어나면_예외를_발생한다(final String nickname) { + // given + final Player player = PlayerFixture.PLAYER(); + + // when & then + assertAll(() -> { + final PlayerException playerException = assertThrows(PlayerException.class, () -> player.editNickname(nickname)); + assertThat(playerException).usingRecursiveComparison().isEqualTo(new PlayerException(PlayerExceptionType.UNAVAILABLE_NICKNAME)); + }); + } + + @MethodSource("availableNicknames") + @ParameterizedTest + void 플레이어_닉네임을_변경한다(final String nickname) { + // given + final Player player = PlayerFixture.PLAYER(); + + // when + player.editNickname(nickname); + + // then + assertThat(player.getNickname()).isEqualTo(nickname); + } + + @Test + void 잘못된_문자로_닉네임_입력이_들어오면_잘못된_문자_지우고_20글자로_잘라서_플레이어를_생성한다() { + // given + final String input = "루!#@!#@카".repeat(100); + final String expected ="루카".repeat(10); + + // when + final Player player = Player.create(input, new Score(0), MemberFixture.MEMBER()); + + // then + assertThat(player.getNickname()).isEqualTo(expected); + } + + static Stream unavailableNicknames() { + return Stream.of( + "특수문자#$%@닉네임", + "10글자가 넘는 닉네임입니다. 이것은 안됩니다.12345678", + "1" + ); + } + + static Stream availableNicknames() { + return Stream.of( + "가능한 닉네임", + "루카20살", + "hello" + ); + } +} diff --git a/backend/src/test/java/com/now/naaga/player/persistence/repository/PlayerRepositoryTest.java b/backend/src/test/java/com/now/naaga/player/persistence/repository/PlayerRepositoryTest.java index e977ebffa..5a0a8e4eb 100644 --- a/backend/src/test/java/com/now/naaga/player/persistence/repository/PlayerRepositoryTest.java +++ b/backend/src/test/java/com/now/naaga/player/persistence/repository/PlayerRepositoryTest.java @@ -2,26 +2,14 @@ import static org.assertj.core.api.Assertions.assertThat; -import com.now.naaga.common.builder.PlayerBuilder; +import com.now.naaga.common.AbstractTest; import com.now.naaga.player.domain.Player; -import org.junit.jupiter.api.DisplayNameGeneration; -import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.jdbc.Sql; @SuppressWarnings("NonAsciiCharacters") -@DisplayNameGeneration(ReplaceUnderscores.class) -@Sql("/truncate.sql") @SpringBootTest -class PlayerRepositoryTest { - - @Autowired - PlayerRepository playerRepository; - - @Autowired - private PlayerBuilder playerBuilder; +class PlayerRepositoryTest extends AbstractTest { @Test void 맴버아이디로_플레이어를_조회한다() { diff --git a/backend/src/test/java/com/now/naaga/player/presentation/PlayerControllerTest.java b/backend/src/test/java/com/now/naaga/player/presentation/PlayerControllerTest.java index 327c177a5..f849cccbd 100644 --- a/backend/src/test/java/com/now/naaga/player/presentation/PlayerControllerTest.java +++ b/backend/src/test/java/com/now/naaga/player/presentation/PlayerControllerTest.java @@ -1,68 +1,150 @@ package com.now.naaga.player.presentation; -import static com.now.naaga.common.exception.CommonExceptionType.INVALID_REQUEST_PARAMETERS; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.SoftAssertions.assertSoftly; - import com.now.naaga.auth.domain.AuthToken; import com.now.naaga.auth.infrastructure.AuthType; -import com.now.naaga.auth.infrastructure.jwt.AuthTokenGenerator; -import com.now.naaga.common.CommonControllerTest; -import com.now.naaga.common.builder.PlayerBuilder; +import com.now.naaga.common.ControllerTest; +import com.now.naaga.common.exception.CommonExceptionType; import com.now.naaga.common.exception.ExceptionResponse; import com.now.naaga.player.domain.Player; +import com.now.naaga.player.presentation.dto.EditPlayerRequest; +import com.now.naaga.player.presentation.dto.EditPlayerResponse; +import com.now.naaga.player.presentation.dto.PlayerResponse; import com.now.naaga.player.presentation.dto.RankResponse; import com.now.naaga.score.domain.Score; import io.restassured.RestAssured; import io.restassured.common.mapper.TypeRef; +import io.restassured.http.ContentType; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; -import java.time.LocalDateTime; -import java.util.List; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayNameGeneration; -import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; +import java.time.LocalDateTime; +import java.util.List; + +import static com.now.naaga.common.exception.CommonExceptionType.INVALID_REQUEST_PARAMETERS; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.SoftAssertions.assertSoftly; + @SuppressWarnings("NonAsciiCharacters") -@DisplayNameGeneration(ReplaceUnderscores.class) -public class PlayerControllerTest extends CommonControllerTest { +public class PlayerControllerTest extends ControllerTest { + + @Test + void 닉네임을_변경한다() { + // given + final String nickname = "변경된 닉네임"; + final Player player = playerBuilder.init().build(); + final EditPlayerRequest editPlayerRequest = new EditPlayerRequest(nickname); + + final AuthToken generate = authTokenGenerator.generate(player.getMember(), 1L, AuthType.KAKAO); + final String accessToken = generate.getAccessToken(); + // when + final ExtractableResponse response = RestAssured.given().log().all() + .contentType(MediaType.APPLICATION_JSON_VALUE) + .header("Authorization", "Bearer " + accessToken) + .body(editPlayerRequest) + .when().patch("/profiles/my") + .then().log().all() + .extract(); + + // then + final EditPlayerResponse expected = new EditPlayerResponse(nickname); + final EditPlayerResponse actual = response.as(EditPlayerResponse.class); + final int statusCode = response.statusCode(); + + assertSoftly(softAssertions -> { + softAssertions.assertThat(actual) + .usingRecursiveComparison() + .isEqualTo(expected); + softAssertions.assertThat(statusCode) + .isEqualTo(HttpStatus.OK.value()); + }); + } + + @Test + void 잘못된_닉네임을_입력하면_예외를_응답한다() { + // given + final String nickname = "변경된 닉네임!!"; + final Player player = playerBuilder.init().build(); + final EditPlayerRequest editPlayerRequest = new EditPlayerRequest(nickname); + + final AuthToken generate = authTokenGenerator.generate(player.getMember(), 1L, AuthType.KAKAO); + final String accessToken = generate.getAccessToken(); + // when + final ExtractableResponse response = RestAssured.given().log().all() + .contentType(MediaType.APPLICATION_JSON_VALUE) + .header("Authorization", "Bearer " + accessToken) + .body(editPlayerRequest) + .when().patch("/profiles/my") + .then().log().all() + .extract(); + + // then + final CommonExceptionType exceptionType = CommonExceptionType.INVALID_REQUEST_BODY; + final ExceptionResponse expected = new ExceptionResponse(exceptionType.errorCode(), exceptionType.errorMessage()); + final ExceptionResponse actual = response.as(ExceptionResponse.class); + final int statusCode = response.statusCode(); - @Autowired - private AuthTokenGenerator authTokenGenerator; + assertSoftly(softAssertions -> { + softAssertions.assertThat(actual) + .usingRecursiveComparison() + .isEqualTo(expected); + softAssertions.assertThat(statusCode) + .isEqualTo(HttpStatus.BAD_REQUEST.value()); + }); + } + + + @Test + void 플레이어_정보를_정상적으로_조회한다() { + //given + final Player player = playerBuilder.init() + .build(); + + //when + final ExtractableResponse extract = RestAssured + .given().log().all() + .header("Authorization", authorizationForBearer(player)) + .contentType(ContentType.JSON) + .when() + .get("/profiles/my") + .then().log().all() + .extract(); - @Autowired - private PlayerBuilder playerBuilder; + //then + final int statusCode = extract.statusCode(); + final PlayerResponse actual = extract.as(PlayerResponse.class); + final PlayerResponse expected = PlayerResponse.from(player); - @BeforeEach - protected void setUp() { - super.setUp(); + assertSoftly(softAssertions -> { + softAssertions.assertThat(statusCode).isEqualTo(HttpStatus.OK.value()); + softAssertions.assertThat(actual) + .usingRecursiveComparison() + .isEqualTo(expected); + } + ); } @Test void 멤버의_랭크를_조회한다() { // given final Player player = playerBuilder.init() - .totalScore(new Score(15)) - .build(); + .totalScore(new Score(15)) + .build(); playerBuilder.init() - .totalScore(new Score(20)) - .build(); + .totalScore(new Score(20)) + .build(); playerBuilder.init() - .totalScore(new Score(30)) - .build(); - - final AuthToken generate = authTokenGenerator.generate(player.getMember(), 1L, AuthType.KAKAO); - final String accessToken = generate.getAccessToken(); + .totalScore(new Score(30)) + .build(); // when - final ExtractableResponse response = RestAssured.given().log().all() + final ExtractableResponse response = RestAssured + .given().log().all() + .header("Authorization", authorizationForBearer(player)) .contentType(MediaType.APPLICATION_JSON_VALUE) - .header("Authorization", "Bearer " + accessToken) .when().get("/ranks/my") .then().log().all() .statusCode(HttpStatus.OK.value()) @@ -85,25 +167,25 @@ protected void setUp() { void 모든_맴버의_랭크를_조회한다() { // given final Player player1 = playerBuilder.init() - .totalScore(new Score(15)) - .build(); + .totalScore(new Score(15)) + .build(); final Player player2 = playerBuilder.init() - .totalScore(new Score(20)) - .build(); + .totalScore(new Score(20)) + .build(); final Player player3 = playerBuilder.init() - .totalScore(new Score(30)) - .build(); + .totalScore(new Score(30)) + .build(); // when final ExtractableResponse response = RestAssured.given() - .log().all() - .contentType(MediaType.APPLICATION_JSON_VALUE) - .when().get("/ranks?sort-by=rank&order=ascending") - .then().log().all() - .statusCode(HttpStatus.OK.value()) - .extract(); + .log().all() + .contentType(MediaType.APPLICATION_JSON_VALUE) + .when().get("/ranks?sort-by=rank&order=ascending") + .then().log().all() + .statusCode(HttpStatus.OK.value()) + .extract(); // then final List rankResponseList = response.as(new TypeRef<>() { @@ -122,29 +204,28 @@ protected void setUp() { assertThat(thirdRank.getRank()).isEqualTo(3); } - // TODO: 요청 파라미터가 잘못돼었을때(o) @Test void 모든_맴버의_랭크를_조회할때_요청_파라미터가_없으면_예외를_발생시킨다() { // given final Player player1 = playerBuilder.init() - .totalScore(new Score(15)) - .build(); + .totalScore(new Score(15)) + .build(); final Player player2 = playerBuilder.init() - .totalScore(new Score(20)) - .build(); + .totalScore(new Score(20)) + .build(); final Player player3 = playerBuilder.init() - .totalScore(new Score(30)) - .build(); + .totalScore(new Score(30)) + .build(); // when final ExtractableResponse response = RestAssured.given() - .log().all() - .contentType(MediaType.APPLICATION_JSON_VALUE) - .when().get("/ranks?sort-by=rank&order=decending") - .then().log().all() - .extract(); + .log().all() + .contentType(MediaType.APPLICATION_JSON_VALUE) + .when().get("/ranks?sort-by=rank&order=decending") + .then().log().all() + .extract(); // then final int statusCode = response.statusCode(); @@ -152,13 +233,13 @@ protected void setUp() { final ExceptionResponse expected = new ExceptionResponse(INVALID_REQUEST_PARAMETERS.errorCode(), INVALID_REQUEST_PARAMETERS.errorMessage()); assertSoftly(softAssertions -> { - softAssertions.assertThat(statusCode).isEqualTo(HttpStatus.BAD_REQUEST.value()); - softAssertions.assertThat(actual) - .usingRecursiveComparison() - .ignoringExpectedNullFields() - .ignoringFieldsOfTypes(LocalDateTime.class) - .isEqualTo(expected); - } - ); + softAssertions.assertThat(statusCode).isEqualTo(HttpStatus.BAD_REQUEST.value()); + softAssertions.assertThat(actual) + .usingRecursiveComparison() + .ignoringExpectedNullFields() + .ignoringFieldsOfTypes(LocalDateTime.class) + .isEqualTo(expected); + } + ); } } diff --git a/backend/src/test/java/com/now/naaga/temporaryplace/application/TemporaryPlaceServiceTest.java b/backend/src/test/java/com/now/naaga/temporaryplace/application/TemporaryPlaceServiceTest.java index c94edf149..338865759 100644 --- a/backend/src/test/java/com/now/naaga/temporaryplace/application/TemporaryPlaceServiceTest.java +++ b/backend/src/test/java/com/now/naaga/temporaryplace/application/TemporaryPlaceServiceTest.java @@ -1,82 +1,61 @@ package com.now.naaga.temporaryplace.application; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.mockito.Mockito.anyString; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; -import com.now.naaga.common.builder.TemporaryPlaceBuilder; -import com.now.naaga.common.infrastructure.AwsS3FileManager; +import com.now.naaga.common.ServiceTest; import com.now.naaga.temporaryplace.domain.TemporaryPlace; -import com.now.naaga.temporaryplace.repository.TemporaryPlaceRepository; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.DisplayNameGeneration; -import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; import org.junit.jupiter.api.Test; -import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.jdbc.Sql; @SuppressWarnings("NonAsciiCharacters") -@DisplayNameGeneration(ReplaceUnderscores.class) -@Sql("/truncate.sql") -@ActiveProfiles("test") -@SpringBootTest -class TemporaryPlaceServiceTest { - - @Autowired - private TemporaryPlaceRepository temporaryPlaceRepository; - +class TemporaryPlaceServiceTest extends ServiceTest { + @Autowired private TemporaryPlaceService temporaryPlaceService; - - @Autowired - private TemporaryPlaceBuilder temporaryPlaceBuilder; - - @MockBean - private AwsS3FileManager awsS3FileManager; - + @Test void 장소가_생성될_때_ID로_검수_장소_데이터만_삭제된다() { // given final TemporaryPlace temporaryPlace = temporaryPlaceBuilder.init() .build(); - + final Long id = temporaryPlace.getId(); - + // when temporaryPlaceService.deleteByIdWhenPlaceCreated(id); - + // then final TemporaryPlace actual = temporaryPlaceRepository.findById(id) .orElse(null); - + assertAll( () -> assertThat(actual).isNull(), () -> verify(awsS3FileManager, times(0)).deleteFile(anyString()) - ); + ); } - + @Test void 검수_장소_등록이_거절될_때_ID로_검수_장소_데이터_삭제_및_S3_이미지_파일이_함께_삭제된다() { // given final TemporaryPlace temporaryPlace = temporaryPlaceBuilder.init() .build(); - + final Long id = temporaryPlace.getId(); - + // when temporaryPlaceService.deleteByIdWhenTemporaryPlaceDenied(id); - + // then final TemporaryPlace actual = temporaryPlaceRepository.findById(id) .orElse(null); - + assertAll( () -> assertThat(actual).isNull(), () -> verify(awsS3FileManager, times(1)).deleteFile(anyString()) - ); + ); } } diff --git a/backend/src/test/java/com/now/naaga/temporaryplace/presentation/TemporaryPlaceControllerTest.java b/backend/src/test/java/com/now/naaga/temporaryplace/presentation/TemporaryPlaceControllerTest.java index a20681bf9..808338a5a 100644 --- a/backend/src/test/java/com/now/naaga/temporaryplace/presentation/TemporaryPlaceControllerTest.java +++ b/backend/src/test/java/com/now/naaga/temporaryplace/presentation/TemporaryPlaceControllerTest.java @@ -1,54 +1,24 @@ package com.now.naaga.temporaryplace.presentation; -import static io.restassured.RestAssured.given; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.SoftAssertions.assertSoftly; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doReturn; import com.fasterxml.jackson.core.JsonProcessingException; -import com.now.naaga.auth.infrastructure.jwt.AuthTokenGenerator; -import com.now.naaga.common.CommonControllerTest; -import com.now.naaga.common.builder.PlaceBuilder; -import com.now.naaga.common.builder.PlayerBuilder; -import com.now.naaga.common.builder.TemporaryPlaceBuilder; +import com.now.naaga.common.ControllerTest; import com.now.naaga.temporaryplace.domain.TemporaryPlace; import com.now.naaga.temporaryplace.presentation.dto.TemporaryPlaceResponse; import io.restassured.RestAssured; import io.restassured.common.mapper.TypeRef; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; - import java.io.FileNotFoundException; import java.util.List; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayNameGeneration; -import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpStatus; -import org.springframework.test.context.ActiveProfiles; @SuppressWarnings("NonAsciiCharacters") -@DisplayNameGeneration(ReplaceUnderscores.class) -@ActiveProfiles("test") -class TemporaryPlaceControllerTest extends CommonControllerTest { - - @Autowired - private TemporaryPlaceBuilder temporaryPlaceBuilder; - - @Autowired - private PlaceBuilder placeBuilder; - - @Autowired - private PlayerBuilder playerBuilder; - - @Autowired - private AuthTokenGenerator authTokenGenerator; - -// @SpyBean -// private FileManager fileManager; +class TemporaryPlaceControllerTest extends ControllerTest { @Value("${manager.id}") private String id; @@ -56,11 +26,6 @@ class TemporaryPlaceControllerTest extends CommonControllerTest { @Value("${manager.password}") private String password; - @BeforeEach - void setup() { - super.setUp(); - } - // @Test // void 검수할_장소_등록_요청을_받으면_201_상태코드와_함께_추가된_검수할_장소_정보를_응답한다() throws FileNotFoundException { // //given @@ -116,17 +81,17 @@ void setup() { void 검수할_장소_목록_조회_요청을_받으면_200_상태코드와_함께_검수할_장소_목록을_응답한다() throws FileNotFoundException, JsonProcessingException { //given final TemporaryPlace temporaryPlace = temporaryPlaceBuilder.init() - .build(); + .build(); //when - final ExtractableResponse extract = given() - .log().all() - .auth().preemptive().basic(id, password) - .when() - .get("/temporary-places") - .then() - .log().all() - .extract(); + final ExtractableResponse extract = RestAssured.given() + .log().all() + .auth().preemptive().basic(id, password) + .when() + .get("/temporary-places") + .then() + .log().all() + .extract(); final int statusCode = extract.statusCode(); final List actual = extract.as(new TypeRef<>() { }); @@ -135,25 +100,25 @@ void setup() { assertSoftly(softAssertions -> { softAssertions.assertThat(statusCode).isEqualTo(HttpStatus.OK.value()); softAssertions.assertThat(expected) - .usingRecursiveComparison() - .isEqualTo(actual); + .usingRecursiveComparison() + .isEqualTo(actual); }); } void ID를_통한_삭제_요청이_성공하면_204_응답코드를_반환한다() { // given final TemporaryPlace temporaryPlace = temporaryPlaceBuilder.init() - .build(); + .build(); // when final ExtractableResponse extract = RestAssured.given() - .log().all() - .auth().preemptive().basic(id, password) - .when() - .delete("/temporary-places/{temporaryPlaceId}", temporaryPlace.getId()) - .then() - .log().all() - .extract(); + .log().all() + .auth().preemptive().basic(id, password) + .when() + .delete("/temporary-places/{temporaryPlaceId}", temporaryPlace.getId()) + .then() + .log().all() + .extract(); // then final int statusCode = extract.statusCode();