mirror of https://github.com/usbharu/Hideout.git
Compare commits
No commits in common. "03243602c504e221a3f4f050d092783cbdfd3085" and "727d69606c41907f5cb94c277c8dea8cdb0771c4" have entirely different histories.
03243602c5
...
727d69606c
|
|
@ -32,11 +32,6 @@ tasks.withType<Test> {
|
|||
val cpus = Runtime.getRuntime().availableProcessors()
|
||||
maxParallelForks = max(1, cpus - 1)
|
||||
setForkEvery(4)
|
||||
doFirst {
|
||||
jvmArgs = arrayOf(
|
||||
"--add-opens", "java.base/java.lang=ALL-UNNAMED"
|
||||
).toMutableList()
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask<*>>().configureEach {
|
||||
|
|
@ -165,8 +160,7 @@ dependencies {
|
|||
testImplementation("org.junit.jupiter:junit-jupiter:5.8.1")
|
||||
testImplementation("org.mockito.kotlin:mockito-kotlin:4.1.0")
|
||||
testImplementation("org.mockito:mockito-inline:5.2.0")
|
||||
testImplementation("nl.jqno.equalsverifier:equalsverifier:3.15.3")
|
||||
testImplementation("com.jparams:to-string-verifier:1.4.8")
|
||||
|
||||
|
||||
implementation("org.drewcarlson:kjob-core:0.6.0")
|
||||
implementation("org.drewcarlson:kjob-mongo:0.6.0")
|
||||
|
|
|
|||
|
|
@ -1,42 +0,0 @@
|
|||
package dev.usbharu.hideout
|
||||
|
||||
import com.jparams.verifier.tostring.ToStringVerifier
|
||||
import nl.jqno.equalsverifier.EqualsVerifier
|
||||
import nl.jqno.equalsverifier.Warning
|
||||
import nl.jqno.equalsverifier.internal.reflection.PackageScanner
|
||||
import org.junit.jupiter.api.Test
|
||||
import java.lang.reflect.Modifier
|
||||
import kotlin.test.assertFails
|
||||
|
||||
class EqualsAndToStringTest {
|
||||
@Test
|
||||
fun equalsTest() {
|
||||
assertFails {
|
||||
EqualsVerifier
|
||||
.simple()
|
||||
.suppress(Warning.INHERITED_DIRECTLY_FROM_OBJECT)
|
||||
.forPackage("dev.usbharu.hideout", true)
|
||||
.verify()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun toStringTest() {
|
||||
|
||||
PackageScanner.getClassesIn("dev.usbharu.hideout", null, true)
|
||||
.filter {
|
||||
it != null && !it.isEnum && !it.isInterface && !Modifier.isAbstract(it.modifiers)
|
||||
}
|
||||
.forEach {
|
||||
try {
|
||||
ToStringVerifier.forClass(it).verify()
|
||||
} catch (e: AssertionError) {
|
||||
println(it.name)
|
||||
e.printStackTrace()
|
||||
} catch (e: Exception) {
|
||||
println(it.name)
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,144 +0,0 @@
|
|||
package dev.usbharu.hideout.core.service.post
|
||||
|
||||
import dev.usbharu.hideout.activitypub.service.activity.create.ApSendCreateService
|
||||
import dev.usbharu.hideout.application.config.CharacterLimit
|
||||
import dev.usbharu.hideout.core.domain.model.post.Post
|
||||
import dev.usbharu.hideout.core.domain.model.post.PostRepository
|
||||
import dev.usbharu.hideout.core.domain.model.user.UserRepository
|
||||
import dev.usbharu.hideout.core.query.PostQueryService
|
||||
import dev.usbharu.hideout.core.service.timeline.TimelineService
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.jetbrains.exposed.exceptions.ExposedSQLException
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.extension.ExtendWith
|
||||
import org.mockito.InjectMocks
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito
|
||||
import org.mockito.Mockito.mockStatic
|
||||
import org.mockito.Spy
|
||||
import org.mockito.junit.jupiter.MockitoExtension
|
||||
import org.mockito.kotlin.*
|
||||
import org.springframework.dao.DuplicateKeyException
|
||||
import utils.PostBuilder
|
||||
import utils.UserBuilder
|
||||
import java.time.Instant
|
||||
|
||||
@ExtendWith(MockitoExtension::class)
|
||||
class PostServiceImplTest {
|
||||
|
||||
@Mock
|
||||
private lateinit var postRepository: PostRepository
|
||||
|
||||
@Mock
|
||||
private lateinit var userRepository: UserRepository
|
||||
|
||||
@Mock
|
||||
private lateinit var timelineService: TimelineService
|
||||
|
||||
@Mock
|
||||
private lateinit var postQueryService: PostQueryService
|
||||
|
||||
@Spy
|
||||
private var postBuilder: Post.PostBuilder = Post.PostBuilder(CharacterLimit())
|
||||
|
||||
@Mock
|
||||
private lateinit var apSendCreateService: ApSendCreateService
|
||||
|
||||
@InjectMocks
|
||||
private lateinit var postServiceImpl: PostServiceImpl
|
||||
|
||||
@Test
|
||||
fun `createLocal 正常にpostを作成できる`() = runTest {
|
||||
|
||||
val now = Instant.now()
|
||||
val post = PostBuilder.of(createdAt = now.toEpochMilli())
|
||||
|
||||
whenever(postRepository.save(eq(post))).doReturn(true)
|
||||
whenever(postRepository.generateId()).doReturn(post.id)
|
||||
whenever(userRepository.findById(eq(post.userId))).doReturn(UserBuilder.localUserOf(id = post.userId))
|
||||
whenever(timelineService.publishTimeline(eq(post), eq(true))).doReturn(Unit)
|
||||
|
||||
mockStatic(Instant::class.java, Mockito.CALLS_REAL_METHODS).use {
|
||||
|
||||
it.`when`<Instant>(Instant::now).doReturn(now)
|
||||
val createLocal = postServiceImpl.createLocal(
|
||||
PostCreateDto(
|
||||
post.text,
|
||||
post.overview,
|
||||
post.visibility,
|
||||
post.repostId,
|
||||
post.replyId,
|
||||
post.userId,
|
||||
post.mediaIds
|
||||
)
|
||||
)
|
||||
|
||||
assertThat(createLocal).isEqualTo(post)
|
||||
}
|
||||
|
||||
verify(postRepository, times(1)).save(eq(post))
|
||||
verify(timelineService, times(1)).publishTimeline(eq(post), eq(true))
|
||||
verify(apSendCreateService, times(1)).createNote(eq(post))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `createRemote 正常にリモートのpostを作成できる`() = runTest {
|
||||
val post = PostBuilder.of()
|
||||
|
||||
whenever(postRepository.save(eq(post))).doReturn(true)
|
||||
whenever(timelineService.publishTimeline(eq(post), eq(false))).doReturn(Unit)
|
||||
|
||||
val createLocal = postServiceImpl.createRemote(post)
|
||||
|
||||
assertThat(createLocal).isEqualTo(post)
|
||||
|
||||
|
||||
verify(postRepository, times(1)).save(eq(post))
|
||||
verify(timelineService, times(1)).publishTimeline(eq(post), eq(false))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `createRemote 既に作成されていた場合はそのまま帰す`() = runTest {
|
||||
val post = PostBuilder.of()
|
||||
|
||||
whenever(postRepository.save(eq(post))).doReturn(false)
|
||||
|
||||
val createLocal = postServiceImpl.createRemote(post)
|
||||
|
||||
assertThat(createLocal).isEqualTo(post)
|
||||
|
||||
verify(postRepository, times(1)).save(eq(post))
|
||||
verify(timelineService, times(0)).publishTimeline(any(), any())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `createRemote 既に作成されていることを検知できず例外が発生した場合はDBから取得して返す`() = runTest {
|
||||
val post = PostBuilder.of()
|
||||
|
||||
whenever(postRepository.save(eq(post))).doAnswer { throw ExposedSQLException(null, emptyList(), mock()) }
|
||||
whenever(postQueryService.findByApId(eq(post.apId))).doReturn(post)
|
||||
|
||||
val createLocal = postServiceImpl.createRemote(post)
|
||||
|
||||
assertThat(createLocal).isEqualTo(post)
|
||||
|
||||
verify(postRepository, times(1)).save(eq(post))
|
||||
verify(timelineService, times(0)).publishTimeline(any(), any())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `createRemote 既に作成されていることを検知出来ずタイムラインにpush出来なかった場合何もしない`() = runTest {
|
||||
val post = PostBuilder.of()
|
||||
|
||||
whenever(postRepository.save(eq(post))).doReturn(true)
|
||||
whenever(timelineService.publishTimeline(eq(post), eq(false))).doThrow(DuplicateKeyException::class)
|
||||
|
||||
val createLocal = postServiceImpl.createRemote(post)
|
||||
|
||||
assertThat(createLocal).isEqualTo(post)
|
||||
|
||||
verify(postRepository, times(1)).save(eq(post))
|
||||
verify(timelineService, times(1)).publishTimeline(eq(post), eq(false))
|
||||
}
|
||||
}
|
||||
|
|
@ -1,127 +0,0 @@
|
|||
package dev.usbharu.hideout.core.service.reaction
|
||||
|
||||
|
||||
import dev.usbharu.hideout.activitypub.service.activity.like.APReactionService
|
||||
import dev.usbharu.hideout.application.service.id.TwitterSnowflakeIdGenerateService
|
||||
import dev.usbharu.hideout.core.domain.model.reaction.Reaction
|
||||
import dev.usbharu.hideout.core.domain.model.reaction.ReactionRepository
|
||||
import dev.usbharu.hideout.core.query.ReactionQueryService
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.jetbrains.exposed.exceptions.ExposedSQLException
|
||||
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 utils.PostBuilder
|
||||
|
||||
@ExtendWith(MockitoExtension::class)
|
||||
class ReactionServiceImplTest {
|
||||
|
||||
@Mock
|
||||
private lateinit var reactionRepository: ReactionRepository
|
||||
|
||||
@Mock
|
||||
private lateinit var apReactionService: APReactionService
|
||||
|
||||
@Mock
|
||||
private lateinit var reactionQueryService: ReactionQueryService
|
||||
|
||||
@InjectMocks
|
||||
private lateinit var reactionServiceImpl: ReactionServiceImpl
|
||||
|
||||
@Test
|
||||
fun `receiveReaction リアクションが存在しないとき保存する`() = runTest {
|
||||
|
||||
val post = PostBuilder.of()
|
||||
|
||||
whenever(reactionQueryService.reactionAlreadyExist(eq(post.id), eq(post.userId), eq(0))).doReturn(false)
|
||||
val generateId = TwitterSnowflakeIdGenerateService.generateId()
|
||||
whenever(reactionRepository.generateId()).doReturn(generateId)
|
||||
|
||||
reactionServiceImpl.receiveReaction("❤", "example.com", post.userId, post.id)
|
||||
|
||||
verify(reactionRepository, times(1)).save(eq(Reaction(generateId, 0, post.id, post.userId)))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `receiveReaction リアクションが既に作成されていることを検知出来ずに例外が発生した場合は何もしない`() = runTest {
|
||||
val post = PostBuilder.of()
|
||||
|
||||
whenever(reactionQueryService.reactionAlreadyExist(eq(post.id), eq(post.userId), eq(0))).doReturn(false)
|
||||
val generateId = TwitterSnowflakeIdGenerateService.generateId()
|
||||
whenever(
|
||||
reactionRepository.save(
|
||||
eq(
|
||||
Reaction(
|
||||
id = generateId,
|
||||
emojiId = 0,
|
||||
postId = post.id,
|
||||
userId = post.userId
|
||||
)
|
||||
)
|
||||
)
|
||||
).doAnswer {
|
||||
throw ExposedSQLException(
|
||||
null,
|
||||
emptyList(), mock()
|
||||
)
|
||||
}
|
||||
whenever(reactionRepository.generateId()).doReturn(generateId)
|
||||
|
||||
reactionServiceImpl.receiveReaction("❤", "example.com", post.userId, post.id)
|
||||
|
||||
verify(reactionRepository, times(1)).save(eq(Reaction(generateId, 0, post.id, post.userId)))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `receiveReaction リアクションが既に作成されている場合は何もしない`() = runTest() {
|
||||
val post = PostBuilder.of()
|
||||
whenever(reactionQueryService.reactionAlreadyExist(eq(post.id), eq(post.userId), eq(0))).doReturn(true)
|
||||
|
||||
reactionServiceImpl.receiveReaction("❤", "example.com", post.userId, post.id)
|
||||
|
||||
verify(reactionRepository, never()).save(any())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `sendReaction リアクションが存在しないとき保存して配送する`() = runTest {
|
||||
val post = PostBuilder.of()
|
||||
whenever(reactionQueryService.reactionAlreadyExist(eq(post.id), eq(post.userId), eq(0))).doReturn(false)
|
||||
val generateId = TwitterSnowflakeIdGenerateService.generateId()
|
||||
whenever(reactionRepository.generateId()).doReturn(generateId)
|
||||
|
||||
reactionServiceImpl.sendReaction("❤", post.userId, post.id)
|
||||
|
||||
verify(reactionRepository, times(1)).save(eq(Reaction(generateId, 0, post.id, post.userId)))
|
||||
verify(apReactionService, times(1)).reaction(eq(Reaction(generateId, 0, post.id, post.userId)))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `sendReaction リアクションが存在するときは削除して保存して配送する`() = runTest {
|
||||
val post = PostBuilder.of()
|
||||
whenever(reactionQueryService.reactionAlreadyExist(eq(post.id), eq(post.userId), eq(0))).doReturn(true)
|
||||
val generateId = TwitterSnowflakeIdGenerateService.generateId()
|
||||
whenever(reactionRepository.generateId()).doReturn(generateId)
|
||||
|
||||
reactionServiceImpl.sendReaction("❤", post.userId, post.id)
|
||||
|
||||
|
||||
verify(reactionRepository, times(1)).delete(eq(Reaction(generateId, 0, post.id, post.userId)))
|
||||
verify(reactionRepository, times(1)).save(eq(Reaction(generateId, 0, post.id, post.userId)))
|
||||
verify(apReactionService, times(1)).removeReaction(eq(Reaction(generateId, 0, post.id, post.userId)))
|
||||
verify(apReactionService, times(1)).reaction(eq(Reaction(generateId, 0, post.id, post.userId)))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `removeReaction リアクションが存在する場合削除して配送`() = runTest {
|
||||
val post = PostBuilder.of()
|
||||
whenever(reactionQueryService.reactionAlreadyExist(eq(post.id), eq(post.userId), eq(0))).doReturn(true)
|
||||
|
||||
reactionServiceImpl.removeReaction(post.userId, post.id)
|
||||
|
||||
verify(reactionRepository, times(1)).delete(eq(Reaction(0, 0, post.id, post.userId)))
|
||||
verify(apReactionService, times(1)).removeReaction(eq(Reaction(0, 0, post.id, post.userId)))
|
||||
}
|
||||
}
|
||||
|
|
@ -1,110 +0,0 @@
|
|||
package dev.usbharu.hideout.core.service.timeline
|
||||
|
||||
import dev.usbharu.hideout.application.service.id.TwitterSnowflakeIdGenerateService
|
||||
import dev.usbharu.hideout.core.domain.model.post.Visibility
|
||||
import dev.usbharu.hideout.core.domain.model.timeline.Timeline
|
||||
import dev.usbharu.hideout.core.domain.model.timeline.TimelineRepository
|
||||
import dev.usbharu.hideout.core.domain.model.user.User
|
||||
import dev.usbharu.hideout.core.query.FollowerQueryService
|
||||
import dev.usbharu.hideout.core.query.UserQueryService
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.extension.ExtendWith
|
||||
import org.mockito.ArgumentCaptor
|
||||
import org.mockito.Captor
|
||||
import org.mockito.InjectMocks
|
||||
import org.mockito.Mock
|
||||
import org.mockito.junit.jupiter.MockitoExtension
|
||||
import org.mockito.kotlin.*
|
||||
import utils.PostBuilder
|
||||
import utils.UserBuilder
|
||||
|
||||
@ExtendWith(MockitoExtension::class)
|
||||
class TimelineServiceTest {
|
||||
|
||||
@Mock
|
||||
private lateinit var followerQueryService: FollowerQueryService
|
||||
|
||||
@Mock
|
||||
private lateinit var userQueryService: UserQueryService
|
||||
|
||||
@Mock
|
||||
private lateinit var timelineRepository: TimelineRepository
|
||||
|
||||
@InjectMocks
|
||||
private lateinit var timelineService: TimelineService
|
||||
|
||||
@Captor
|
||||
private lateinit var captor: ArgumentCaptor<List<Timeline>>
|
||||
|
||||
@Test
|
||||
fun `publishTimeline ローカルの投稿はローカルのフォロワーと投稿者のタイムラインに追加される`() = runTest {
|
||||
val post = PostBuilder.of()
|
||||
val listOf = listOf<User>(UserBuilder.localUserOf(), UserBuilder.localUserOf())
|
||||
val localUserOf = UserBuilder.localUserOf(id = post.userId)
|
||||
|
||||
whenever(followerQueryService.findFollowersById(eq(post.userId))).doReturn(listOf)
|
||||
whenever(userQueryService.findById(eq(post.userId))).doReturn(localUserOf)
|
||||
whenever(timelineRepository.generateId()).doReturn(TwitterSnowflakeIdGenerateService.generateId())
|
||||
|
||||
|
||||
timelineService.publishTimeline(post, true)
|
||||
|
||||
verify(timelineRepository).saveAll(capture(captor))
|
||||
val timelineList = captor.value
|
||||
|
||||
assertThat(timelineList).hasSize(4).anyMatch { it.userId == post.userId }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `publishTimeline リモートの投稿はローカルのフォロワーのタイムラインに追加される`() = runTest {
|
||||
val post = PostBuilder.of()
|
||||
val listOf = listOf<User>(UserBuilder.localUserOf(), UserBuilder.localUserOf())
|
||||
|
||||
whenever(followerQueryService.findFollowersById(eq(post.userId))).doReturn(listOf)
|
||||
whenever(timelineRepository.generateId()).doReturn(TwitterSnowflakeIdGenerateService.generateId())
|
||||
|
||||
|
||||
timelineService.publishTimeline(post, false)
|
||||
|
||||
verify(timelineRepository).saveAll(capture(captor))
|
||||
val timelineList = captor.value
|
||||
|
||||
assertThat(timelineList).hasSize(3)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `publishTimeline パブリック投稿はパブリックタイムラインにも追加される`() = runTest {
|
||||
val post = PostBuilder.of()
|
||||
val listOf = listOf<User>(UserBuilder.localUserOf(), UserBuilder.localUserOf())
|
||||
|
||||
whenever(followerQueryService.findFollowersById(eq(post.userId))).doReturn(listOf)
|
||||
whenever(timelineRepository.generateId()).doReturn(TwitterSnowflakeIdGenerateService.generateId())
|
||||
|
||||
|
||||
timelineService.publishTimeline(post, false)
|
||||
|
||||
verify(timelineRepository).saveAll(capture(captor))
|
||||
val timelineList = captor.value
|
||||
|
||||
assertThat(timelineList).hasSize(3).anyMatch { it.userId == 0L }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `publishTimeline パブリック投稿ではない場合はローカルのフォロワーのみに追加される`() = runTest {
|
||||
val post = PostBuilder.of(visibility = Visibility.UNLISTED)
|
||||
val listOf = listOf<User>(UserBuilder.localUserOf(), UserBuilder.localUserOf())
|
||||
|
||||
whenever(followerQueryService.findFollowersById(eq(post.userId))).doReturn(listOf)
|
||||
whenever(timelineRepository.generateId()).doReturn(TwitterSnowflakeIdGenerateService.generateId())
|
||||
|
||||
|
||||
timelineService.publishTimeline(post, false)
|
||||
|
||||
verify(timelineRepository).saveAll(capture(captor))
|
||||
val timelineList = captor.value
|
||||
|
||||
assertThat(timelineList).hasSize(2).noneMatch { it.userId == 0L }
|
||||
}
|
||||
}
|
||||
|
|
@ -20,15 +20,15 @@ object UserBuilder {
|
|||
screenName: String = name,
|
||||
description: String = "This user is test user.",
|
||||
password: String = "password-$id",
|
||||
inbox: String = "https://$domain/users/$id/inbox",
|
||||
outbox: String = "https://$domain/users/$id/outbox",
|
||||
url: String = "https://$domain/users/$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/users/$id#pubkey",
|
||||
followers: String = "https://$domain/users/$id/followers",
|
||||
following: String = "https://$domain/users/$id/following"
|
||||
keyId: String = "https://$domain/$id#pubkey",
|
||||
followers: String = "https://$domain/$id/followers",
|
||||
following: String = "https://$domain/$id/following"
|
||||
): User {
|
||||
return userBuilder.of(
|
||||
id = id,
|
||||
|
|
|
|||
Loading…
Reference in New Issue