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("org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version")
|
||||
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-cio:$ktor_version")
|
||||
|
|
|
@ -13,4 +13,26 @@ open class Accept : Object {
|
|||
this.`object` = `object`
|
||||
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()
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "JsonLd(context=$context)"
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,10 @@ open class Object : JsonLd {
|
|||
return result
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "Object(type=$type, name=$name) ${super.toString()}"
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -10,14 +10,14 @@ sealed class ActivityPubResponse(
|
|||
)
|
||||
|
||||
class ActivityPubStringResponse(
|
||||
httpStatusCode: HttpStatusCode,
|
||||
httpStatusCode: HttpStatusCode = HttpStatusCode.OK,
|
||||
val message: String,
|
||||
contentType: ContentType = ContentType.Application.Activity
|
||||
) :
|
||||
ActivityPubResponse(httpStatusCode, contentType)
|
||||
|
||||
class ActivityPubObjectResponse(
|
||||
httpStatusCode: HttpStatusCode,
|
||||
httpStatusCode: HttpStatusCode = HttpStatusCode.OK,
|
||||
val message: JsonLd,
|
||||
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