diff --git a/push-message-provider-hpk/src/test/kotlin/ru/touchin/push/message/provider/hpk/PushMessageProviderHpkTestApplication.kt b/push-message-provider-hpk/src/test/kotlin/ru/touchin/push/message/provider/hpk/PushMessageProviderHpkTestApplication.kt new file mode 100644 index 0000000..46d3f97 --- /dev/null +++ b/push-message-provider-hpk/src/test/kotlin/ru/touchin/push/message/provider/hpk/PushMessageProviderHpkTestApplication.kt @@ -0,0 +1,23 @@ +package ru.touchin.push.message.provider.hpk + +import org.springframework.boot.SpringBootConfiguration +import org.springframework.boot.test.context.TestConfiguration +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Import +import org.springframework.web.reactive.function.client.WebClient +import ru.touchin.logger.spring.configurations.SpringLoggerConfiguration +import ru.touchin.logger.spring.web.configurations.SpringLoggerWebConfiguration + +@TestConfiguration +@SpringBootConfiguration +@EnablePushMessageProviderHpk +@Import( + SpringLoggerConfiguration::class, + SpringLoggerWebConfiguration::class, +) +class PushMessageProviderHpkTestApplication { + + @Bean + fun webClientBuilder(): WebClient.Builder = WebClient.builder() + +} diff --git a/push-message-provider-hpk/src/test/kotlin/ru/touchin/push/message/provider/hpk/base/builders/BuildableTest.kt b/push-message-provider-hpk/src/test/kotlin/ru/touchin/push/message/provider/hpk/base/builders/BuildableTest.kt new file mode 100644 index 0000000..bba59e8 --- /dev/null +++ b/push-message-provider-hpk/src/test/kotlin/ru/touchin/push/message/provider/hpk/base/builders/BuildableTest.kt @@ -0,0 +1,52 @@ +package ru.touchin.push.message.provider.hpk.base.builders + +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test +import ru.touchin.push.message.provider.hpk.base.extensions.ifNotNull + +class BuildableTest { + + @Test + fun ifNotNull_setOnNotNull() { + val data = Data(property = true) + val builder = DataBuilder() + + builder.ifNotNull(data.property) { setProperty(it) } + + Assertions.assertNotNull( + builder.property + ) + } + + @Test + fun ifNotNull_notSetOnNull() { + val data = Data(property = null) + val builder = DataBuilder() + + builder.ifNotNull(data.property) { setProperty(it) } + + Assertions.assertNull( + builder.property + ) + } + + private class Data(val property: Boolean?) + + private class DataBuilder : Buildable { + + var property: Boolean? = null + + fun setProperty(property: Boolean): DataBuilder { + this.property = property + return this + } + + fun build(): Data { + return Data( + property = property, + ) + } + + } + +} diff --git a/push-message-provider-hpk/src/test/kotlin/ru/touchin/push/message/provider/hpk/clients/hms_hpk/HmsHpkWebClientTest.kt b/push-message-provider-hpk/src/test/kotlin/ru/touchin/push/message/provider/hpk/clients/hms_hpk/HmsHpkWebClientTest.kt new file mode 100644 index 0000000..a46d86f --- /dev/null +++ b/push-message-provider-hpk/src/test/kotlin/ru/touchin/push/message/provider/hpk/clients/hms_hpk/HmsHpkWebClientTest.kt @@ -0,0 +1,61 @@ +package ru.touchin.push.message.provider.hpk.clients.hms_hpk + +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.context.SpringBootTest +import ru.touchin.push.message.provider.hpk.clients.hms.enums.HmsResponseCode +import ru.touchin.push.message.provider.hpk.clients.hms_hpk.bodies.HmsHpkMessagesSendBody +import ru.touchin.push.message.provider.hpk.clients.hms_hpk.dto.AndroidConfig +import ru.touchin.push.message.provider.hpk.clients.hms_hpk.dto.Message +import ru.touchin.push.message.provider.hpk.clients.hms_hpk.dto.Notification +import ru.touchin.push.message.provider.hpk.clients.hms_hpk.dto.android.AndroidClickAction +import ru.touchin.push.message.provider.hpk.clients.hms_hpk.dto.android.AndroidNotificationConfig +import ru.touchin.push.message.provider.hpk.clients.hms_hpk.enums.android.AndroidClickActionType +import ru.touchin.push.message.provider.hpk.clients.hms_hpk.enums.android.AndroidUrgency +import ru.touchin.push.message.provider.hpk.clients.hms_hpk.requests.HmsHpkMessagesSendRequest + +@SpringBootTest +class HmsHpkWebClientTest { + + @Autowired + lateinit var hmsHpkWebClient: HmsHpkWebClient + + @Test + fun messagesSend_pushTokenNotSpecified() { + val result = hmsHpkWebClient.messagesSend( + HmsHpkMessagesSendRequest( + hmsHpkMessagesSendBody = HmsHpkMessagesSendBody( + validateOnly = true, + message = Message.builder() + .addToken("pushTokenWithLongLength") + .setNotification( + Notification.builder() + .setTitle("title") + .setBody("body") + .setImage("https://avatars.githubusercontent.com/u/1435794?s=200&v=4") + .build() + ) + .setAndroidConfig( + AndroidConfig.builder() + .setUrgency(AndroidUrgency.HIGH) + .setAndroidNotificationConfig( + AndroidNotificationConfig.builder() + .setDefaultSound(true) + .build(AndroidClickAction.builder().build(AndroidClickActionType.OPEN_APP)) + ) + .build() + ) + .build() + ), + accessToken = "testAccessToken" + ) + ) + + Assertions.assertEquals( + HmsResponseCode.PERMISSION_DENIED.value.toString(), + result.code + ) + } + +} diff --git a/push-message-provider-hpk/src/test/kotlin/ru/touchin/push/message/provider/hpk/clients/hms_oauth/HmsOauthWebClientTest.kt b/push-message-provider-hpk/src/test/kotlin/ru/touchin/push/message/provider/hpk/clients/hms_oauth/HmsOauthWebClientTest.kt new file mode 100644 index 0000000..f03fa1b --- /dev/null +++ b/push-message-provider-hpk/src/test/kotlin/ru/touchin/push/message/provider/hpk/clients/hms_oauth/HmsOauthWebClientTest.kt @@ -0,0 +1,26 @@ +package ru.touchin.push.message.provider.hpk.clients.hms_oauth + +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.context.SpringBootTest +import ru.touchin.push.message.provider.hpk.clients.hms.enums.HmsResponseCode + +@SpringBootTest +class HmsOauthWebClientTest { + + @Autowired + lateinit var hmsOauthWebClient: HmsOauthWebClient + + @Test + fun token_invalidClientSecretOnInvalidClientSecret() { + val result = hmsOauthWebClient.token() + + Assertions.assertNotNull(result.failure) + + Assertions.assertEquals( + result.failure?.error, + HmsResponseCode.INVALID_CLIENT_SECRET.value + ) + } +} diff --git a/push-message-provider-hpk/src/test/kotlin/ru/touchin/push/message/provider/hpk/converters/PushTokenMessageConverterTest.kt b/push-message-provider-hpk/src/test/kotlin/ru/touchin/push/message/provider/hpk/converters/PushTokenMessageConverterTest.kt new file mode 100644 index 0000000..ff05703 --- /dev/null +++ b/push-message-provider-hpk/src/test/kotlin/ru/touchin/push/message/provider/hpk/converters/PushTokenMessageConverterTest.kt @@ -0,0 +1,84 @@ +package ru.touchin.push.message.provider.hpk.converters + +import org.junit.jupiter.api.Test +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.context.SpringBootTest +import ru.touchin.push.message.provider.dto.PushMessageNotification +import ru.touchin.push.message.provider.dto.request.PushTokenMessage +import ru.touchin.push.message.provider.hpk.clients.hms_hpk.dto.Message +import ru.touchin.push.message.provider.hpk.clients.hms_hpk.dto.Notification as HmsNotification +import org.junit.jupiter.api.Assertions +import ru.touchin.push.message.provider.hpk.clients.hms_hpk.dto.AndroidConfig +import ru.touchin.push.message.provider.hpk.clients.hms_hpk.dto.android.AndroidClickAction +import ru.touchin.push.message.provider.hpk.clients.hms_hpk.dto.android.AndroidNotificationConfig +import ru.touchin.push.message.provider.hpk.clients.hms_hpk.enums.android.AndroidClickActionType + +@SpringBootTest +class PushTokenMessageConverterTest { + + @Autowired + lateinit var pushTokenMessageConverter: PushTokenMessageConverter + + @Test + fun invoke_buildsComplexMessage() { + val request = PushTokenMessage( + token = "testToken", + pushMessageNotification = PushMessageNotification( + title = "title", + description = "description", + imageUrl = "https://avatars.githubusercontent.com/u/1435794?s=200&v=4" + ), + data = mapOf( + "key1" to "value1", + ) + ) + + val actualResult = pushTokenMessageConverter(request) + + val expectedResult = Message.builder() + .addToken("testToken") + .setNotification( + HmsNotification.builder() + .setTitle("title") + .setBody("description") + .setImage("https://avatars.githubusercontent.com/u/1435794?s=200&v=4") + .build() + ) + .setAndroidConfig( + AndroidConfig.builder() + .setAndroidNotificationConfig( + AndroidNotificationConfig.builder() + .setDefaultSound(true) + .build(AndroidClickAction.builder().build(AndroidClickActionType.OPEN_APP)) + ) + .build() + ) + .setData("{\"key1\":\"value1\"}") + .build() + + Assertions.assertEquals( + expectedResult, + actualResult + ) + } + + @Test + fun invoke_throwsValidationErrorAtHttpImageUrl() { + val request = PushTokenMessage( + token = "testToken", + pushMessageNotification = PushMessageNotification( + title = "title", + description = "description", + imageUrl = "http://avatars.githubusercontent.com/u/1435794?s=200&v=4" + ), + data = mapOf( + "key1" to "value1", + ) + ) + + Assertions.assertThrows( + IllegalArgumentException::class.java + ) { pushTokenMessageConverter(request) } + } + +} diff --git a/push-message-provider-hpk/src/test/kotlin/ru/touchin/push/message/provider/hpk/services/HmsHpkClientServiceTest.kt b/push-message-provider-hpk/src/test/kotlin/ru/touchin/push/message/provider/hpk/services/HmsHpkClientServiceTest.kt new file mode 100644 index 0000000..9881992 --- /dev/null +++ b/push-message-provider-hpk/src/test/kotlin/ru/touchin/push/message/provider/hpk/services/HmsHpkClientServiceTest.kt @@ -0,0 +1,58 @@ +package ru.touchin.push.message.provider.hpk.services + +import com.nhaarman.mockitokotlin2.any +import org.junit.jupiter.api.Assertions +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 ru.touchin.push.message.provider.dto.PushMessageNotification +import ru.touchin.push.message.provider.dto.request.PushTokenMessage +import ru.touchin.push.message.provider.exceptions.InvalidPushTokenException +import ru.touchin.push.message.provider.hpk.clients.hms_hpk.HmsHpkWebClient +import ru.touchin.push.message.provider.hpk.clients.hms.enums.HmsResponseCode +import ru.touchin.push.message.provider.hpk.clients.hms_hpk.responses.HmsHpkResponse + +@SpringBootTest +class HmsHpkClientServiceTest { + + @MockBean + lateinit var hmsHpkWebClient: HmsHpkWebClient + + @MockBean + lateinit var hmsOauthClientService: HmsOauthClientService + + @Autowired + lateinit var hmsHpkClientService: HmsHpkClientService + + @Test + fun getAccessToken_throwsInvalidPushTokenExceptionForKnownErrors() { + Mockito.`when`(hmsOauthClientService.getAccessToken()).then { "accessToken" } + + Mockito.`when`( + hmsHpkWebClient.messagesSend(any()) + ).then { + HmsHpkResponse( + code = HmsResponseCode.INVALID_TOKEN.value.toString(), + msg = "0", + requestId = "requestId" + ) + } + + val pushTokenMessage = PushTokenMessage( + token = "token", + pushMessageNotification = PushMessageNotification( + title = "title", + description = "description", + imageUrl = null + ), + data = emptyMap() + ) + + Assertions.assertThrows( + InvalidPushTokenException::class.java + ) { hmsHpkClientService.send(pushTokenMessage) } + } + +} diff --git a/push-message-provider-hpk/src/test/kotlin/ru/touchin/push/message/provider/hpk/services/HmsOauthAccessTokenCacheServiceTest.kt b/push-message-provider-hpk/src/test/kotlin/ru/touchin/push/message/provider/hpk/services/HmsOauthAccessTokenCacheServiceTest.kt new file mode 100644 index 0000000..cd62b9d --- /dev/null +++ b/push-message-provider-hpk/src/test/kotlin/ru/touchin/push/message/provider/hpk/services/HmsOauthAccessTokenCacheServiceTest.kt @@ -0,0 +1,88 @@ +package ru.touchin.push.message.provider.hpk.services + +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.context.SpringBootTest +import ru.touchin.push.message.provider.hpk.services.dto.AccessToken +import java.time.Instant + +@SpringBootTest +class HmsOauthAccessTokenCacheServiceTest { + + @Autowired + lateinit var hmsOauthAccessTokenCacheService: HmsOauthAccessTokenCacheService + + private val validAccessToken: AccessToken + get() = AccessToken( + value = "token", + expiresAt = Instant.now().plusSeconds(600) + ) + + private val expiredAccessToken: AccessToken + get() = AccessToken( + value = "token", + expiresAt = Instant.now().minusSeconds(600) + ) + + @Test + fun get_noCacheReturnsNull() { + hmsOauthAccessTokenCacheService.evict() + + val accessToken = hmsOauthAccessTokenCacheService.get() + + Assertions.assertNull(accessToken) + } + + @Test + fun get_validIsReturned() { + val expected = validAccessToken + + hmsOauthAccessTokenCacheService.put(expected) + + val actual = hmsOauthAccessTokenCacheService.get() + + Assertions.assertEquals( + expected, + actual + ) + } + + @Test + fun get_expiredIsNotReturned() { + hmsOauthAccessTokenCacheService.put(expiredAccessToken) + + val accessToken = hmsOauthAccessTokenCacheService.get() + + Assertions.assertNull(accessToken) + } + + @Test + fun put_valid() { + hmsOauthAccessTokenCacheService.put(validAccessToken) + + val result = hmsOauthAccessTokenCacheService.get() + + Assertions.assertNotNull(result) + } + + @Test + fun put_expired() { + hmsOauthAccessTokenCacheService.put(expiredAccessToken) + + val result = hmsOauthAccessTokenCacheService.get() + + Assertions.assertNull(result) + } + + @Test + fun evict_deletesCache() { + hmsOauthAccessTokenCacheService.put(validAccessToken) + hmsOauthAccessTokenCacheService.evict() + + val result = hmsOauthAccessTokenCacheService.get() + + Assertions.assertNull(result) + } + +} diff --git a/push-message-provider-hpk/src/test/kotlin/ru/touchin/push/message/provider/hpk/services/HmsOauthClientServiceTest.kt b/push-message-provider-hpk/src/test/kotlin/ru/touchin/push/message/provider/hpk/services/HmsOauthClientServiceTest.kt new file mode 100644 index 0000000..fd1f7ba --- /dev/null +++ b/push-message-provider-hpk/src/test/kotlin/ru/touchin/push/message/provider/hpk/services/HmsOauthClientServiceTest.kt @@ -0,0 +1,101 @@ +package ru.touchin.push.message.provider.hpk.services + +import com.fasterxml.jackson.databind.JsonMappingException +import org.junit.jupiter.api.Assertions +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 ru.touchin.push.message.provider.exceptions.InvalidPushTokenException +import ru.touchin.push.message.provider.exceptions.PushMessageProviderException +import ru.touchin.push.message.provider.hpk.base.clients.dto.ConditionalResponse +import ru.touchin.push.message.provider.hpk.clients.hms.enums.HmsResponseCode +import ru.touchin.push.message.provider.hpk.clients.hms_oauth.HmsOauthWebClient +import ru.touchin.push.message.provider.hpk.clients.hms_oauth.response.HmsOauthErrorResponse +import ru.touchin.push.message.provider.hpk.clients.hms_oauth.response.HmsOauthTokenResponse +import java.net.SocketTimeoutException + +@SpringBootTest +class HmsOauthClientServiceTest { + + @MockBean + lateinit var hmsOauthWebClient: HmsOauthWebClient + + @Autowired + lateinit var hmsOauthClientService: HmsOauthClientService + + @Test + fun getAccessToken_throwsPushMessageProviderExceptionForUnknownError() { + Mockito.`when`( + hmsOauthWebClient.token() + ).then { + ConditionalResponse( + success = null, + failure = HmsOauthErrorResponse( + error = HmsResponseCode.UNKNOWN.value, + subError = 0, + errorDescription = "errorDescription" + ) + ) + } + + Assertions.assertThrows( + PushMessageProviderException::class.java + ) { hmsOauthClientService.getAccessToken() } + } + + @Test + fun getAccessToken_throwsNetworkExceptions() { + Mockito.`when`( + hmsOauthWebClient.token() + ).then { + throw SocketTimeoutException() + } + + Assertions.assertThrows( + SocketTimeoutException::class.java + ) { hmsOauthClientService.getAccessToken() } + } + + + @Test + fun getAccessToken_throwsParsingExceptions() { + Mockito.`when`( + hmsOauthWebClient.token() + ).then { + throw JsonMappingException({ }, "jsonMappingExceptionMsg") + } + + Assertions.assertThrows( + JsonMappingException::class.java + ) { hmsOauthClientService.getAccessToken() } + } + + @Test + fun getAccessToken_cachesExpectedTime() { + val expected = "accessToken" + + Mockito.`when`( + hmsOauthWebClient.token() + ).then { + ConditionalResponse( + success = HmsOauthTokenResponse( + tokenType = "tokenType", + expiresIn = 60_000, + accessToken = expected + ), + failure = null + ) + } + + val actual = hmsOauthClientService.getAccessToken() + + Assertions.assertEquals( + expected, + actual + ) + } + + +} diff --git a/push-message-provider-hpk/src/test/kotlin/ru/touchin/push/message/provider/hpk/services/PushMessageProviderHpkServiceTest.kt b/push-message-provider-hpk/src/test/kotlin/ru/touchin/push/message/provider/hpk/services/PushMessageProviderHpkServiceTest.kt new file mode 100644 index 0000000..9a79d75 --- /dev/null +++ b/push-message-provider-hpk/src/test/kotlin/ru/touchin/push/message/provider/hpk/services/PushMessageProviderHpkServiceTest.kt @@ -0,0 +1,60 @@ +package ru.touchin.push.message.provider.hpk.services + +import com.nhaarman.mockitokotlin2.any +import com.nhaarman.mockitokotlin2.only +import com.nhaarman.mockitokotlin2.verify +import org.junit.jupiter.api.DisplayName +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 ru.touchin.push.message.provider.dto.request.PushTokenCheck +import ru.touchin.push.message.provider.dto.request.PushTokenMessage +import ru.touchin.push.message.provider.enums.PushTokenStatus +import ru.touchin.push.message.provider.services.PushMessageProviderService + +@SpringBootTest +class PushMessageProviderHpkServiceTest { + + @MockBean + lateinit var hmsHpkClientService: HmsHpkClientService + + @Autowired + lateinit var pushMessageProviderService: PushMessageProviderService + + @Test + @DisplayName("Обработка запроса на отправку единичного сообщения происходит корректно") + fun send_basic() { + Mockito.`when`( + hmsHpkClientService.send(any()) + ).then { + // returns Unit + } + + val request = PushTokenMessage( + token = "testTokenWithLongLength", + pushMessageNotification = null, + data = emptyMap() + ) + + pushMessageProviderService.send(request) + + verify(hmsHpkClientService, only()).send(any()) + } + + @Test + @DisplayName("Обработка запроса на валидацию пуш-токена происходит корректно") + fun check_basic() { + Mockito.`when`( + hmsHpkClientService.check(any()) + ).then { + PushTokenStatus.UNKNOWN + } + + pushMessageProviderService.check(PushTokenCheck("testTokenWithLongLength")) + + verify(hmsHpkClientService, only()).check(any()) + } + +} diff --git a/push-message-provider-hpk/src/test/resources/application.yml b/push-message-provider-hpk/src/test/resources/application.yml new file mode 100644 index 0000000..3ae0e53 --- /dev/null +++ b/push-message-provider-hpk/src/test/resources/application.yml @@ -0,0 +1,20 @@ +push-message-provider: + platformProviders: + ANDROID_HUAWEI: + - HPK + hpk: + web-services: + client-id: 1 + oauth: + client-secret: 2 + url: https://oauth-login.cloud.huawei.com/oauth2/v3/ + http: + connection-timeout: 5s + read-timeout: 10s + write-timeout: 10s + hpk: + url: https://push-api.cloud.huawei.com/v1/ + http: + connection-timeout: 5s + read-timeout: 10s + write-timeout: 10s