mirror of https://github.com/usbharu/Hideout.git
test: フォロー受付処理のJobのテストを追加
This commit is contained in:
parent
71ad3c9c7d
commit
f4df345407
|
@ -65,6 +65,7 @@ dependencies {
|
||||||
testImplementation("io.ktor:ktor-server-tests-jvm:$ktor_version")
|
testImplementation("io.ktor:ktor-server-tests-jvm:$ktor_version")
|
||||||
testImplementation("org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version")
|
testImplementation("org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version")
|
||||||
testImplementation ("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.4")
|
testImplementation ("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.4")
|
||||||
|
testImplementation("io.ktor:ktor-client-mock:$ktor_version")
|
||||||
|
|
||||||
implementation("io.ktor:ktor-client-core:$ktor_version")
|
implementation("io.ktor:ktor-client-core:$ktor_version")
|
||||||
implementation("io.ktor:ktor-client-cio:$ktor_version")
|
implementation("io.ktor:ktor-client-cio:$ktor_version")
|
||||||
|
|
|
@ -13,4 +13,26 @@ open class Accept : Object {
|
||||||
this.`object` = `object`
|
this.`object` = `object`
|
||||||
this.actor = actor
|
this.actor = actor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (other !is Accept) return false
|
||||||
|
if (!super.equals(other)) return false
|
||||||
|
|
||||||
|
if (`object` != other.`object`) return false
|
||||||
|
return actor == other.actor
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = super.hashCode()
|
||||||
|
result = 31 * result + (`object`?.hashCode() ?: 0)
|
||||||
|
result = 31 * result + (actor?.hashCode() ?: 0)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return "Accept(`object`=$`object`, actor=$actor) ${super.toString()}"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,10 @@ open class JsonLd {
|
||||||
return context.hashCode()
|
return context.hashCode()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return "JsonLd(context=$context)"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,10 @@ open class Object : JsonLd {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return "Object(type=$type, name=$name) ${super.toString()}"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,14 +10,14 @@ sealed class ActivityPubResponse(
|
||||||
)
|
)
|
||||||
|
|
||||||
class ActivityPubStringResponse(
|
class ActivityPubStringResponse(
|
||||||
httpStatusCode: HttpStatusCode,
|
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)
|
||||||
|
|
||||||
class ActivityPubObjectResponse(
|
class ActivityPubObjectResponse(
|
||||||
httpStatusCode: HttpStatusCode,
|
httpStatusCode: HttpStatusCode = HttpStatusCode.OK,
|
||||||
val message: JsonLd,
|
val message: JsonLd,
|
||||||
contentType: ContentType = ContentType.Application.Activity
|
contentType: ContentType = ContentType.Application.Activity
|
||||||
) :
|
) :
|
||||||
|
|
|
@ -0,0 +1,153 @@
|
||||||
|
@file:OptIn(ExperimentalCoroutinesApi::class)
|
||||||
|
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||||
|
|
||||||
|
package dev.usbharu.hideout.service.activitypub
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.module.kotlin.readValue
|
||||||
|
import dev.usbharu.hideout.ap.*
|
||||||
|
import dev.usbharu.hideout.config.Config
|
||||||
|
import dev.usbharu.hideout.config.ConfigData
|
||||||
|
import dev.usbharu.hideout.domain.model.UserEntity
|
||||||
|
import dev.usbharu.hideout.domain.model.job.ReceiveFollowJob
|
||||||
|
import dev.usbharu.hideout.service.impl.UserService
|
||||||
|
import dev.usbharu.hideout.service.job.JobQueueParentService
|
||||||
|
import io.ktor.client.*
|
||||||
|
import io.ktor.client.engine.mock.*
|
||||||
|
import kjob.core.dsl.ScheduleContext
|
||||||
|
import kjob.core.job.JobProps
|
||||||
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
|
import kotlinx.coroutines.test.runTest
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.mockito.ArgumentMatchers.anyString
|
||||||
|
import org.mockito.kotlin.*
|
||||||
|
import utils.JsonObjectMapper
|
||||||
|
|
||||||
|
class ActivityPubFollowServiceImplTest {
|
||||||
|
@Test
|
||||||
|
fun `receiveFollow フォロー受付処理`() = runTest {
|
||||||
|
val jobQueueParentService = mock<JobQueueParentService> {
|
||||||
|
onBlocking { schedule(eq(ReceiveFollowJob), any()) } doReturn Unit
|
||||||
|
}
|
||||||
|
val activityPubFollowService = ActivityPubFollowServiceImpl(jobQueueParentService, mock(), mock(), mock())
|
||||||
|
activityPubFollowService.receiveFollow(
|
||||||
|
Follow(
|
||||||
|
emptyList(),
|
||||||
|
"Follow",
|
||||||
|
"https://example.com",
|
||||||
|
"https://follower.example.com"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
verify(jobQueueParentService, times(1)).schedule(eq(ReceiveFollowJob), any())
|
||||||
|
argumentCaptor<ScheduleContext<ReceiveFollowJob>.(ReceiveFollowJob) -> Unit> {
|
||||||
|
verify(jobQueueParentService, times(1)).schedule(eq(ReceiveFollowJob), capture())
|
||||||
|
val scheduleContext = ScheduleContext<ReceiveFollowJob>(Json)
|
||||||
|
firstValue.invoke(scheduleContext, ReceiveFollowJob)
|
||||||
|
val actor = scheduleContext.props.props[ReceiveFollowJob.actor.name]
|
||||||
|
val targetActor = scheduleContext.props.props[ReceiveFollowJob.targetActor.name]
|
||||||
|
val follow = scheduleContext.props.props[ReceiveFollowJob.follow.name]
|
||||||
|
assertEquals("https://follower.example.com", actor)
|
||||||
|
assertEquals("https://example.com", targetActor)
|
||||||
|
assertEquals(
|
||||||
|
"""{"type":"Follow","name":"Follow","object":"https://example.com","actor":"https://follower.example.com","@context":null}""",
|
||||||
|
follow
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `receiveFollowJob フォロー受付処理のJob`() = runTest {
|
||||||
|
Config.configData = ConfigData(objectMapper = JsonObjectMapper.objectMapper)
|
||||||
|
val person = Person(
|
||||||
|
type = emptyList(),
|
||||||
|
name = "follower",
|
||||||
|
id = "https://follower.example.com",
|
||||||
|
preferredUsername = "followerUser",
|
||||||
|
summary = "This user is follower user.",
|
||||||
|
inbox = "https://follower.example.com/inbox",
|
||||||
|
outbox = "https://follower.example.com/outbox",
|
||||||
|
url = "https://follower.example.com",
|
||||||
|
icon = Image(
|
||||||
|
type = emptyList(),
|
||||||
|
name = "https://follower.example.com/image",
|
||||||
|
mediaType = "image/png",
|
||||||
|
url = "https://follower.example.com/image"
|
||||||
|
),
|
||||||
|
publicKey = Key(
|
||||||
|
type = emptyList(),
|
||||||
|
name = "Public Key",
|
||||||
|
id = "https://follower.example.com#main-key",
|
||||||
|
owner = "https://follower.example.com",
|
||||||
|
publicKeyPem = "BEGIN PUBLIC KEY...END PUBLIC KEY",
|
||||||
|
)
|
||||||
|
|
||||||
|
)
|
||||||
|
val activityPubUserService = mock<ActivityPubUserService> {
|
||||||
|
onBlocking { fetchPerson(anyString()) } doReturn person
|
||||||
|
}
|
||||||
|
val userService = mock<UserService> {
|
||||||
|
onBlocking { findByUrls(any()) } doReturn listOf(
|
||||||
|
UserEntity(
|
||||||
|
id = 1L,
|
||||||
|
name = "test",
|
||||||
|
domain = "example.com",
|
||||||
|
screenName = "testUser",
|
||||||
|
description = "This user is test user.",
|
||||||
|
inbox = "https://example.com/inbox",
|
||||||
|
outbox = "https://example.com/outbox",
|
||||||
|
url = "https://example.com"
|
||||||
|
),
|
||||||
|
UserEntity(
|
||||||
|
id = 2L,
|
||||||
|
name = "follower",
|
||||||
|
domain = "follower.example.com",
|
||||||
|
screenName = "followerUser",
|
||||||
|
description = "This user is test follower user.",
|
||||||
|
inbox = "https://follower.example.com/inbox",
|
||||||
|
outbox = "https://follower.example.com/outbox",
|
||||||
|
url = "https://follower.example.com"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
onBlocking { addFollowers(any(), any()) } doReturn Unit
|
||||||
|
}
|
||||||
|
val activityPubFollowService =
|
||||||
|
ActivityPubFollowServiceImpl(
|
||||||
|
mock(),
|
||||||
|
activityPubUserService,
|
||||||
|
userService,
|
||||||
|
HttpClient(MockEngine { httpRequestData ->
|
||||||
|
assertEquals(person.inbox, httpRequestData.url.toString())
|
||||||
|
val accept = Accept(
|
||||||
|
type = emptyList(),
|
||||||
|
name = "Follow",
|
||||||
|
`object` = Follow(
|
||||||
|
type = emptyList(),
|
||||||
|
name = "Follow",
|
||||||
|
`object` = "https://example.com",
|
||||||
|
actor = "https://follower.example.com"
|
||||||
|
),
|
||||||
|
actor = "https://example.com"
|
||||||
|
)
|
||||||
|
accept.context += "https://www.w3.org/ns/activitystreams"
|
||||||
|
assertEquals(
|
||||||
|
accept,
|
||||||
|
Config.configData.objectMapper.readValue<Accept>(
|
||||||
|
httpRequestData.body.toByteArray().decodeToString()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
respondOk()
|
||||||
|
})
|
||||||
|
)
|
||||||
|
activityPubFollowService.receiveFollowJob(
|
||||||
|
JobProps(
|
||||||
|
data = mapOf<String, Any>(
|
||||||
|
ReceiveFollowJob.actor.name to "https://follower.example.com",
|
||||||
|
ReceiveFollowJob.targetActor.name to "https://example.com",
|
||||||
|
ReceiveFollowJob.follow.name to """{"type":"Follow","name":"Follow","object":"https://example.com","actor":"https://follower.example.com","@context":null}"""
|
||||||
|
),
|
||||||
|
json = Json
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude
|
||||||
|
import com.fasterxml.jackson.annotation.JsonSetter
|
||||||
|
import com.fasterxml.jackson.annotation.Nulls
|
||||||
|
import com.fasterxml.jackson.databind.DeserializationFeature
|
||||||
|
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
||||||
|
|
||||||
|
object JsonObjectMapper {
|
||||||
|
val objectMapper: com.fasterxml.jackson.databind.ObjectMapper =
|
||||||
|
jacksonObjectMapper().enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
|
||||||
|
.setSerializationInclusion(JsonInclude.Include.NON_EMPTY)
|
||||||
|
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
|
||||||
|
|
||||||
|
init {
|
||||||
|
objectMapper.configOverride(List::class.java).setSetterInfo(
|
||||||
|
JsonSetter.Value.forValueNulls(
|
||||||
|
Nulls.AS_EMPTY
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue