test: noteのエンドポイントのテストを追加

This commit is contained in:
usbharu 2023-11-05 14:46:20 +09:00
parent d650586a7a
commit 117a97123c
4 changed files with 133 additions and 7 deletions

View File

@ -128,6 +128,7 @@ dependencies {
implementation("org.jetbrains.exposed:exposed-java-time:$exposed_version") implementation("org.jetbrains.exposed:exposed-java-time:$exposed_version")
testImplementation("org.springframework.boot:spring-boot-test-autoconfigure") testImplementation("org.springframework.boot:spring-boot-test-autoconfigure")
testImplementation("org.springframework.boot:spring-boot-starter-test") testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("org.springframework.security:spring-security-test")
implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310") implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin") implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.springframework.security:spring-security-oauth2-jose") implementation("org.springframework.security:spring-security-oauth2-jose")

View File

@ -2,15 +2,12 @@ package dev.usbharu.hideout.activitypub.interfaces.api.note
import dev.usbharu.hideout.activitypub.domain.model.Note import dev.usbharu.hideout.activitypub.domain.model.Note
import org.springframework.http.ResponseEntity import org.springframework.http.ResponseEntity
import org.springframework.security.core.annotation.CurrentSecurityContext
import org.springframework.security.core.context.SecurityContext
import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable import org.springframework.web.bind.annotation.PathVariable
interface NoteApController { interface NoteApController {
@GetMapping("/users/*/posts/{postId}") @GetMapping("/users/*/posts/{postId}")
suspend fun postsAp( suspend fun postsAp(
@PathVariable("postId") postId: Long, @PathVariable("postId") postId: Long
@CurrentSecurityContext context: SecurityContext
): ResponseEntity<Note> ): ResponseEntity<Note>
} }

View File

@ -4,8 +4,7 @@ import dev.usbharu.hideout.activitypub.domain.model.Note
import dev.usbharu.hideout.activitypub.service.objects.note.NoteApApiService import dev.usbharu.hideout.activitypub.service.objects.note.NoteApApiService
import dev.usbharu.hideout.core.infrastructure.springframework.httpsignature.HttpSignatureUser import dev.usbharu.hideout.core.infrastructure.springframework.httpsignature.HttpSignatureUser
import org.springframework.http.ResponseEntity import org.springframework.http.ResponseEntity
import org.springframework.security.core.annotation.CurrentSecurityContext import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.security.core.context.SecurityContext
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken
import org.springframework.web.bind.annotation.PathVariable import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RestController import org.springframework.web.bind.annotation.RestController
@ -14,8 +13,8 @@ import org.springframework.web.bind.annotation.RestController
class NoteApControllerImpl(private val noteApApiService: NoteApApiService) : NoteApController { class NoteApControllerImpl(private val noteApApiService: NoteApApiService) : NoteApController {
override suspend fun postsAp( override suspend fun postsAp(
@PathVariable(value = "postId") postId: Long, @PathVariable(value = "postId") postId: Long,
@CurrentSecurityContext context: SecurityContext
): ResponseEntity<Note> { ): ResponseEntity<Note> {
val context = SecurityContextHolder.getContext()
val userId = val userId =
if (context.authentication is PreAuthenticatedAuthenticationToken && if (context.authentication is PreAuthenticatedAuthenticationToken &&
context.authentication.details is HttpSignatureUser context.authentication.details is HttpSignatureUser

View File

@ -0,0 +1,129 @@
package dev.usbharu.hideout.activitypub.interfaces.api.note
import dev.usbharu.hideout.activitypub.domain.model.Note
import dev.usbharu.hideout.activitypub.service.objects.note.NoteApApiService
import dev.usbharu.hideout.application.config.ActivityPubConfig
import dev.usbharu.hideout.core.infrastructure.springframework.httpsignature.HttpSignatureUser
import dev.usbharu.httpsignature.common.HttpHeaders
import dev.usbharu.httpsignature.common.HttpMethod
import dev.usbharu.httpsignature.common.HttpRequest
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.mockito.InjectMocks
import org.mockito.Mock
import org.mockito.junit.jupiter.MockitoExtension
import org.mockito.kotlin.*
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.anonymous
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication
import org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity
import org.springframework.security.web.DefaultSecurityFilterChain
import org.springframework.security.web.FilterChainProxy
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken
import org.springframework.security.web.util.matcher.AnyRequestMatcher
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.get
import org.springframework.test.web.servlet.setup.MockMvcBuilders
import org.springframework.test.web.servlet.setup.StandaloneMockMvcBuilder
import java.net.URL
@ExtendWith(MockitoExtension::class)
class NoteApControllerImplTest {
private lateinit var mockMvc: MockMvc
@Mock
private lateinit var noteApApiService: NoteApApiService
@InjectMocks
private lateinit var noteApControllerImpl: NoteApControllerImpl
@BeforeEach
fun setUp() {
mockMvc = MockMvcBuilders.standaloneSetup(noteApControllerImpl)
.apply<StandaloneMockMvcBuilder>(
springSecurity(
FilterChainProxy(
DefaultSecurityFilterChain(
AnyRequestMatcher.INSTANCE
)
)
)
)
.build()
}
@Test
fun `postAP 匿名で取得できる`() = runTest {
val note = Note(
name = "Note",
id = "https://example.com/users/hoge/posts/1234",
attributedTo = "https://example.com/users/hoge",
content = "Hello",
published = "2023-11-02T15:30:34.160Z"
)
whenever(noteApApiService.getNote(eq(1234), isNull())).doReturn(
note
)
val objectMapper = ActivityPubConfig().objectMapper()
mockMvc
.get("/users/hoge/posts/1234") {
with(anonymous())
}
.asyncDispatch()
.andExpect { status { isOk() } }
.andExpect { content { json(objectMapper.writeValueAsString(note)) } }
}
@Test
fun `postAP 存在しない場合は404`() = runTest {
whenever(noteApApiService.getNote(eq(123), isNull())).doReturn(null)
mockMvc
.get("/users/hoge/posts/123") {
with(anonymous())
}
.asyncDispatch()
.andExpect { status { isNotFound() } }
}
@Test
fun `postAP 認証に成功している場合userIdがnullでない`() = runTest {
val note = Note(
name = "Note",
id = "https://example.com/users/hoge/posts/1234",
attributedTo = "https://example.com/users/hoge",
content = "Hello",
published = "2023-11-02T15:30:34.160Z"
)
whenever(noteApApiService.getNote(eq(1234), isNotNull())).doReturn(note)
val objectMapper = ActivityPubConfig().objectMapper()
val preAuthenticatedAuthenticationToken = PreAuthenticatedAuthenticationToken(
"", HttpRequest(
URL("https://follower.example.com"),
HttpHeaders(
mapOf()
), HttpMethod.GET
)
).apply { details = HttpSignatureUser("fuga", "follower.example.com", 123, true, true, mutableListOf()) }
SecurityContextHolder.getContext().authentication = preAuthenticatedAuthenticationToken
mockMvc.get("/users/hoge/posts/1234") {
with(
authentication(
preAuthenticatedAuthenticationToken
)
)
}.asyncDispatch()
.andExpect { status { isOk() } }
.andExpect { content { json(objectMapper.writeValueAsString(note)) } }
}
}