test: APAcceptServiceImplのテストを追加

This commit is contained in:
usbharu 2023-10-29 16:36:24 +09:00
parent 6dd9400113
commit 0e665dac34
3 changed files with 230 additions and 5 deletions

View File

@ -7,18 +7,78 @@ import io.ktor.http.*
sealed class ActivityPubResponse( sealed class ActivityPubResponse(
val httpStatusCode: HttpStatusCode, val httpStatusCode: HttpStatusCode,
val contentType: ContentType = ContentType.Application.Activity val contentType: ContentType = ContentType.Application.Activity
) ) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is ActivityPubResponse) return false
if (httpStatusCode != other.httpStatusCode) return false
if (contentType != other.contentType) return false
return true
}
override fun hashCode(): Int {
var result = httpStatusCode.hashCode()
result = 31 * result + contentType.hashCode()
return result
}
override fun toString(): String {
return "ActivityPubResponse(httpStatusCode=$httpStatusCode, contentType=$contentType)"
}
}
class ActivityPubStringResponse( class ActivityPubStringResponse(
httpStatusCode: HttpStatusCode = HttpStatusCode.OK, httpStatusCode: HttpStatusCode = HttpStatusCode.OK,
val message: String, val message: String,
contentType: ContentType = ContentType.Application.Activity contentType: ContentType = ContentType.Application.Activity
) : ) : ActivityPubResponse(httpStatusCode, contentType) {
ActivityPubResponse(httpStatusCode, contentType)
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is ActivityPubStringResponse) return false
if (message != other.message) return false
return true
}
override fun hashCode(): Int {
return message.hashCode()
}
override fun toString(): String {
return "ActivityPubStringResponse(message='$message') ${super.toString()}"
}
}
class ActivityPubObjectResponse( class ActivityPubObjectResponse(
httpStatusCode: HttpStatusCode = HttpStatusCode.OK, httpStatusCode: HttpStatusCode = HttpStatusCode.OK,
val message: JsonLd, val message: JsonLd,
contentType: ContentType = ContentType.Application.Activity contentType: ContentType = ContentType.Application.Activity
) : ) : ActivityPubResponse(httpStatusCode, contentType) {
ActivityPubResponse(httpStatusCode, contentType) override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is ActivityPubObjectResponse) return false
if (message != other.message) return false
return true
}
override fun hashCode(): Int {
return message.hashCode()
}
override fun toString(): String {
return "ActivityPubObjectResponse(message=$message) ${super.toString()}"
}
}

View File

@ -0,0 +1,110 @@
package dev.usbharu.hideout.service.ap
import dev.usbharu.hideout.domain.model.ActivityPubStringResponse
import dev.usbharu.hideout.domain.model.ap.Accept
import dev.usbharu.hideout.domain.model.ap.Follow
import dev.usbharu.hideout.domain.model.ap.Like
import dev.usbharu.hideout.exception.ap.IllegalActivityPubObjectException
import dev.usbharu.hideout.query.FollowerQueryService
import dev.usbharu.hideout.query.UserQueryService
import dev.usbharu.hideout.service.user.UserService
import io.ktor.http.*
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
import org.mockito.kotlin.*
import utils.TestTransaction
import utils.UserBuilder
class APAcceptServiceImplTest {
@Test
fun `receiveAccept 正常なAcceptを処理できる`() = runTest {
val actor = "https://example.com"
val follower = "https://follower.example.com"
val targetUser = UserBuilder.localUserOf()
val followerUser = UserBuilder.localUserOf()
val userQueryService = mock<UserQueryService> {
onBlocking { findByUrl(eq(actor)) } doReturn targetUser
onBlocking { findByUrl(eq(follower)) } doReturn followerUser
}
val followerQueryService = mock<FollowerQueryService> {
onBlocking { alreadyFollow(eq(targetUser.id), eq(followerUser.id)) } doReturn false
}
val userService = mock<UserService>()
val apAcceptServiceImpl =
APAcceptServiceImpl(userService, userQueryService, followerQueryService, TestTransaction)
val accept = Accept(
name = "Accept",
`object` = Follow(
name = "",
`object` = actor,
actor = follower
),
actor = actor
)
val actual = apAcceptServiceImpl.receiveAccept(accept)
assertEquals(ActivityPubStringResponse(HttpStatusCode.OK, "accepted"), actual)
verify(userService, times(1)).follow(eq(targetUser.id), eq(followerUser.id))
}
@Test
fun `receiveAccept 既にフォローしている場合は無視する`() = runTest {
val actor = "https://example.com"
val follower = "https://follower.example.com"
val targetUser = UserBuilder.localUserOf()
val followerUser = UserBuilder.localUserOf()
val userQueryService = mock<UserQueryService> {
onBlocking { findByUrl(eq(actor)) } doReturn targetUser
onBlocking { findByUrl(eq(follower)) } doReturn followerUser
}
val followerQueryService = mock<FollowerQueryService> {
onBlocking { alreadyFollow(eq(targetUser.id), eq(followerUser.id)) } doReturn true
}
val userService = mock<UserService>()
val apAcceptServiceImpl =
APAcceptServiceImpl(userService, userQueryService, followerQueryService, TestTransaction)
val accept = Accept(
name = "Accept",
`object` = Follow(
name = "",
`object` = actor,
actor = follower
),
actor = actor
)
val actual = apAcceptServiceImpl.receiveAccept(accept)
assertEquals(ActivityPubStringResponse(HttpStatusCode.OK, "accepted"), actual)
verify(userService, times(0)).follow(eq(targetUser.id), eq(followerUser.id))
}
@Test
fun `revieveAccept AcceptのobjectのtypeがFollow以外の場合IllegalActivityPubObjectExceptionがthrowされる`() =
runTest {
val accept = Accept(
name = "Accept",
`object` = Like(
name = "Like",
actor = "actor",
id = "https://example.com",
`object` = "https://example.com",
content = "aaaa"
),
actor = "https://example.com"
)
val apAcceptServiceImpl = APAcceptServiceImpl(mock(), mock(), mock(), TestTransaction)
assertThrows<IllegalActivityPubObjectException> {
apAcceptServiceImpl.receiveAccept(accept)
}
}
}

View File

@ -0,0 +1,55 @@
package utils
import dev.usbharu.hideout.config.ApplicationConfig
import dev.usbharu.hideout.config.CharacterLimit
import dev.usbharu.hideout.domain.model.hideout.entity.User
import dev.usbharu.hideout.service.core.TwitterSnowflakeIdGenerateService
import kotlinx.coroutines.runBlocking
import java.net.URL
import java.time.Instant
object UserBuilder {
private val userBuilder = User.UserBuilder(CharacterLimit(), ApplicationConfig(URL("https://example.com")))
private val idGenerator = TwitterSnowflakeIdGenerateService
suspend fun localUserOf(
id: Long = generateId(),
name: String = "test-user-$id",
domain: String = "example.com",
screenName: String = name,
description: String = "This user is test user.",
password: String = "password-$id",
inbox: String = "https://$domain/$id/inbox",
outbox: String = "https://$domain/$id/outbox",
url: String = "https://$domain/$id/",
publicKey: String = "-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----",
privateKey: String = "-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----",
createdAt: Instant = Instant.now(),
keyId: String = "https://$domain/$id#pubkey",
followers: String = "https://$domain/$id/followers",
following: String = "https://$domain/$id/following"
): User {
return userBuilder.of(
id = id,
name = name,
domain = domain,
screenName = screenName,
description = description,
password = password,
inbox = inbox,
outbox = outbox,
url = url,
publicKey = publicKey,
privateKey = privateKey,
createdAt = createdAt,
keyId = keyId,
followers = following,
following = followers
)
}
private fun generateId(): Long = runBlocking {
idGenerator.generateId()
}
}