test #426
@@ -0,0 +1,132 @@
|
|||||||
|
package kr.co.vividnext.sodalive.v2.usercreatorchat.websocket
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
|
import kr.co.vividnext.sodalive.jwt.TokenProvider
|
||||||
|
import kr.co.vividnext.sodalive.member.Member
|
||||||
|
import kr.co.vividnext.sodalive.member.MemberAdapter
|
||||||
|
import kr.co.vividnext.sodalive.v2.usercreatorchat.service.UserCreatorChatService
|
||||||
|
import org.junit.jupiter.api.Assertions.assertFalse
|
||||||
|
import org.junit.jupiter.api.Assertions.assertNotNull
|
||||||
|
import org.junit.jupiter.api.Assertions.assertSame
|
||||||
|
import org.junit.jupiter.api.Assertions.assertTrue
|
||||||
|
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 org.springframework.context.ApplicationContext
|
||||||
|
import org.springframework.http.HttpHeaders
|
||||||
|
import org.springframework.http.server.ServerHttpResponse
|
||||||
|
import org.springframework.http.server.ServletServerHttpRequest
|
||||||
|
import org.springframework.mock.web.MockHttpServletRequest
|
||||||
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
|
||||||
|
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping
|
||||||
|
import org.springframework.web.socket.WebSocketHandler
|
||||||
|
import org.springframework.web.socket.server.support.WebSocketHttpRequestHandler
|
||||||
|
|
||||||
|
@SpringBootTest(
|
||||||
|
classes = [
|
||||||
|
UserCreatorChatWebSocketConfig::class,
|
||||||
|
UserCreatorChatWebSocketHandler::class,
|
||||||
|
UserCreatorChatWebSocketAuthInterceptor::class
|
||||||
|
]
|
||||||
|
)
|
||||||
|
class UserCreatorChatWebSocketHandshakeIntegrationTest @Autowired constructor(
|
||||||
|
private val applicationContext: ApplicationContext
|
||||||
|
) {
|
||||||
|
@MockBean
|
||||||
|
private lateinit var tokenProvider: TokenProvider
|
||||||
|
|
||||||
|
@MockBean
|
||||||
|
private lateinit var service: UserCreatorChatService
|
||||||
|
|
||||||
|
@MockBean
|
||||||
|
private lateinit var presenceService: UserCreatorChatPresenceService
|
||||||
|
|
||||||
|
@MockBean
|
||||||
|
private lateinit var sessionRegistry: UserCreatorChatWebSocketSessionRegistry
|
||||||
|
|
||||||
|
@MockBean
|
||||||
|
private lateinit var objectMapper: ObjectMapper
|
||||||
|
|
||||||
|
private val response = Mockito.mock(ServerHttpResponse::class.java)
|
||||||
|
private val wsHandler = Mockito.mock(WebSocketHandler::class.java)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("유효한 Bearer token이 있으면 등록된 WebSocket auth interceptor가 handshake를 허용한다")
|
||||||
|
fun shouldAcceptHandshakeWithValidBearerToken() {
|
||||||
|
val member = Member(email = "ws-handshake@test.com", password = "pw", nickname = "ws-handshake")
|
||||||
|
.apply { id = 10L }
|
||||||
|
val authentication = UsernamePasswordAuthenticationToken(MemberAdapter(member), "valid-token")
|
||||||
|
Mockito.`when`(tokenProvider.validateToken("valid-token")).thenReturn(true)
|
||||||
|
Mockito.`when`(tokenProvider.getAuthentication("valid-token")).thenReturn(authentication)
|
||||||
|
val attributes = mutableMapOf<String, Any>()
|
||||||
|
|
||||||
|
val result = authInterceptor().beforeHandshake(
|
||||||
|
requestWithAuthorization("Bearer valid-token"),
|
||||||
|
response,
|
||||||
|
wsHandler,
|
||||||
|
attributes
|
||||||
|
)
|
||||||
|
|
||||||
|
assertTrue(result)
|
||||||
|
assertSame(authentication, attributes[UserCreatorChatWebSocketAuthInterceptor.AUTHENTICATION_ATTRIBUTE])
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Authorization header가 없으면 등록된 WebSocket auth interceptor가 handshake를 거부한다")
|
||||||
|
fun shouldRejectHandshakeWithoutAuthorizationHeader() {
|
||||||
|
val attributes = mutableMapOf<String, Any>()
|
||||||
|
|
||||||
|
val result = authInterceptor().beforeHandshake(
|
||||||
|
requestWithAuthorization(null),
|
||||||
|
response,
|
||||||
|
wsHandler,
|
||||||
|
attributes
|
||||||
|
)
|
||||||
|
|
||||||
|
assertFalse(result)
|
||||||
|
assertTrue(attributes.isEmpty())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("유효하지 않은 token이면 등록된 WebSocket auth interceptor가 handshake를 거부한다")
|
||||||
|
fun shouldRejectHandshakeWithInvalidBearerToken() {
|
||||||
|
Mockito.`when`(tokenProvider.validateToken("invalid-token")).thenReturn(false)
|
||||||
|
val attributes = mutableMapOf<String, Any>()
|
||||||
|
|
||||||
|
val result = authInterceptor().beforeHandshake(
|
||||||
|
requestWithAuthorization("Bearer invalid-token"),
|
||||||
|
response,
|
||||||
|
wsHandler,
|
||||||
|
attributes
|
||||||
|
)
|
||||||
|
|
||||||
|
assertFalse(result)
|
||||||
|
assertTrue(attributes.isEmpty())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun authInterceptor(): UserCreatorChatWebSocketAuthInterceptor {
|
||||||
|
val handler = registeredWebSocketHandler()
|
||||||
|
return handler.handshakeInterceptors.filterIsInstance<UserCreatorChatWebSocketAuthInterceptor>().single()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun registeredWebSocketHandler(): WebSocketHttpRequestHandler {
|
||||||
|
val handlerMappings = applicationContext.getBeansOfType(SimpleUrlHandlerMapping::class.java).values
|
||||||
|
val urlMap = handlerMappings.flatMap { mapping -> mapping.urlMap.entries }
|
||||||
|
val handler = urlMap.firstNotNullOfOrNull { (path, handler) ->
|
||||||
|
if (path == UserCreatorChatWebSocketConfig.ENDPOINT) handler as? WebSocketHttpRequestHandler else null
|
||||||
|
}
|
||||||
|
assertNotNull(handler, "Expected /ws/v2/user-creator-chat to be registered")
|
||||||
|
return handler!!
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun requestWithAuthorization(authorization: String?): ServletServerHttpRequest {
|
||||||
|
val request = MockHttpServletRequest()
|
||||||
|
if (authorization != null) {
|
||||||
|
request.addHeader(HttpHeaders.AUTHORIZATION, authorization)
|
||||||
|
}
|
||||||
|
return ServletServerHttpRequest(request)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user