diff --git a/hideout-core/src/test/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/APNoteServiceImplTest.kt b/hideout-core/src/test/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/APNoteServiceImplTest.kt index 3520c53a..87bfbae4 100644 --- a/hideout-core/src/test/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/APNoteServiceImplTest.kt +++ b/hideout-core/src/test/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/APNoteServiceImplTest.kt @@ -23,16 +23,18 @@ import dev.usbharu.hideout.activitypub.domain.model.Image import dev.usbharu.hideout.activitypub.domain.model.Key import dev.usbharu.hideout.activitypub.domain.model.Note import dev.usbharu.hideout.activitypub.domain.model.Person +import dev.usbharu.hideout.activitypub.query.AnnounceQueryService import dev.usbharu.hideout.activitypub.query.NoteQueryService import dev.usbharu.hideout.activitypub.service.common.APResourceResolveService +import dev.usbharu.hideout.activitypub.service.objects.emoji.EmojiService import dev.usbharu.hideout.activitypub.service.objects.note.APNoteServiceImpl.Companion.public import dev.usbharu.hideout.activitypub.service.objects.user.APUserService import dev.usbharu.hideout.application.config.CharacterLimit import dev.usbharu.hideout.application.config.HtmlSanitizeConfig import dev.usbharu.hideout.application.service.id.TwitterSnowflakeIdGenerateService -import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.domain.model.post.Post import dev.usbharu.hideout.core.domain.model.post.PostRepository +import dev.usbharu.hideout.core.service.media.MediaService import dev.usbharu.hideout.core.service.post.DefaultPostContentFormatter import dev.usbharu.hideout.core.service.post.PostService import io.ktor.client.* @@ -53,28 +55,58 @@ 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.junit.jupiter.api.extension.ExtendWith +import org.mockito.InjectMocks +import org.mockito.Mock +import org.mockito.Spy +import org.mockito.junit.jupiter.MockitoExtension import org.mockito.kotlin.* import utils.PostBuilder import utils.UserBuilder import java.time.Instant - +@ExtendWith(MockitoExtension::class) class APNoteServiceImplTest { - val postBuilder = Post.PostBuilder( + @Mock + private lateinit var postRepository: PostRepository + + @Mock + private lateinit var apUserService: APUserService + + @Mock + private lateinit var postService: PostService + + @Mock + private lateinit var apResourceResolverService: APResourceResolveService + + @Spy + private val postBuilder: Post.PostBuilder = Post.PostBuilder( CharacterLimit(), DefaultPostContentFormatter(HtmlSanitizeConfig().policy()), Validation.buildDefaultValidatorFactory().validator ) + @Mock + private lateinit var noteQueryService: NoteQueryService + + @Mock + private lateinit var mediaService: MediaService + + @Mock + private lateinit var emojiService: EmojiService + + @Mock + private lateinit var announceQueryService: AnnounceQueryService + + @InjectMocks + private lateinit var apNoteServiceImpl: APNoteServiceImpl + @Test fun `fetchNote(String,String) ノートが既に存在する場合はDBから取得したものを返す`() = runTest { val url = "https://example.com/note" val post = PostBuilder.of() val user = UserBuilder.localUserOf(id = post.actorId) - val actorQueryService = mock { - onBlocking { findById(eq(post.actorId)) } doReturn user - } val expected = Note( id = post.apId, attributedTo = user.url, @@ -85,20 +117,8 @@ class APNoteServiceImplTest { cc = listOfNotNull(public, user.followers), inReplyTo = null ) - val noteQueryService = mock { - onBlocking { findByApid(eq(url)) } doReturn (expected to post) - } - val apNoteServiceImpl = APNoteServiceImpl( - postRepository = mock(), - apUserService = mock(), - postService = mock(), - apResourceResolveService = mock(), - postBuilder = postBuilder, - noteQueryService = noteQueryService, - mock(), - mock(), - mock() - ) + + whenever(noteQueryService.findByApid(eq(url))).doReturn(expected to post) val actual = apNoteServiceImpl.fetchNote(url) @@ -123,12 +143,11 @@ class APNoteServiceImplTest { cc = listOfNotNull(public, user.followers), inReplyTo = null ) - val apResourceResolveService = mock { - onBlocking { resolve(eq(url), any(), isNull()) } doReturn note - } - val noteQueryService = mock { - onBlocking { findByApid(eq(url)) } doReturn null - } + + whenever(apResourceResolverService.resolve(eq(url), any(), isNull())).doReturn(note) + + whenever(noteQueryService.findByApid(eq(url))).doReturn(null) + val person = Person( name = user.name, id = user.url, @@ -153,23 +172,16 @@ class APNoteServiceImplTest { manuallyApprovesFollowers = false ) - val apUserService = mock { - onBlocking { fetchPersonWithEntity(eq(note.attributedTo), isNull(), anyOrNull()) } doReturn (person to user) - } - val postRepository = mock { - onBlocking { generateId() } doReturn TwitterSnowflakeIdGenerateService.generateId() - } - val apNoteServiceImpl = APNoteServiceImpl( - postRepository = postRepository, - apUserService = apUserService, - postService = mock(), - apResourceResolveService = apResourceResolveService, - postBuilder = postBuilder, - noteQueryService = noteQueryService, - mock(), - mock { }, - mock() - ) + + whenever( + apUserService.fetchPersonWithEntity( + eq(note.attributedTo), + isNull(), + anyOrNull() + ) + ).doReturn(person to user) + + whenever(postRepository.generateId()).doReturn(TwitterSnowflakeIdGenerateService.generateId()) val actual = apNoteServiceImpl.fetchNote(url) @@ -181,17 +193,16 @@ class APNoteServiceImplTest { fun `fetchNote(String,String) ノートをリモートから取得した際にエラーが返ってきたらFailedToGetActivityPubResourceExceptionがthrowされる`() = runTest { val url = "https://example.com/note" - - val apResourceResolveService = mock { - val responseData = HttpResponseData( - HttpStatusCode.BadRequest, - GMTDate(), - Headers.Empty, - HttpProtocolVersion.HTTP_1_1, - NullBody, - Dispatchers.IO - ) - onBlocking { resolve(eq(url), any(), isNull()) } doThrow ClientRequestException( + val responseData = HttpResponseData( + HttpStatusCode.BadRequest, + GMTDate(), + Headers.Empty, + HttpProtocolVersion.HTTP_1_1, + NullBody, + Dispatchers.IO + ) + whenever(apResourceResolverService.resolve(eq(url), any(), isNull())).doThrow( + ClientRequestException( DefaultHttpResponse( HttpClientCall( HttpClient(), HttpRequestData( @@ -205,22 +216,10 @@ class APNoteServiceImplTest { ), responseData ), "" ) - } - val noteQueryService = mock { - onBlocking { findByApid(eq(url)) } doReturn null - } - val apNoteServiceImpl = APNoteServiceImpl( - postRepository = mock(), - apUserService = mock(), - postService = mock(), - apResourceResolveService = apResourceResolveService, - postBuilder = postBuilder, - noteQueryService = noteQueryService, - mock(), - mock(), - mock { } ) + whenever(noteQueryService.findByApid(eq(url))).doReturn(null) + assertThrows { apNoteServiceImpl.fetchNote(url) } } @@ -230,9 +229,9 @@ class APNoteServiceImplTest { val user = UserBuilder.localUserOf() val generateId = TwitterSnowflakeIdGenerateService.generateId() val post = PostBuilder.of(id = generateId, userId = user.id) - val postRepository = mock { - onBlocking { generateId() } doReturn generateId - } + + whenever(postRepository.generateId()).doReturn(generateId) + val person = Person( name = user.name, id = user.url, @@ -254,24 +253,10 @@ class APNoteServiceImplTest { following = user.following, followers = user.followers ) - val apUserService = mock { - onBlocking { fetchPersonWithEntity(eq(user.url), anyOrNull(), anyOrNull()) } doReturn (person to user) - } - val postService = mock() - val noteQueryService = mock { - onBlocking { findByApid(eq(post.apId)) } doReturn null - } - val apNoteServiceImpl = APNoteServiceImpl( - postRepository = postRepository, - apUserService = apUserService, - postService = postService, - apResourceResolveService = mock(), - postBuilder = postBuilder, - noteQueryService = noteQueryService, - mock(), - mock(), - mock() - ) + + whenever(apUserService.fetchPersonWithEntity(eq(user.url), anyOrNull(), anyOrNull())).doReturn(person to user) + + whenever(noteQueryService.findByApid(eq(post.apId))).doReturn(null) val note = Note( id = post.apId, @@ -312,21 +297,8 @@ class APNoteServiceImplTest { cc = listOfNotNull(public, user.followers), inReplyTo = null ) - val noteQueryService = mock { - onBlocking { findByApid(eq(post.apId)) } doReturn (note to post) - } - val apNoteServiceImpl = APNoteServiceImpl( - postRepository = mock(), - apUserService = mock(), - postService = mock(), - apResourceResolveService = mock(), - postBuilder = postBuilder, - noteQueryService = noteQueryService, - mock(), - mock(), - mock() - ) + whenever(noteQueryService.findByApid(post.apId)).doReturn(note to post) val fetchNote = apNoteServiceImpl.fetchNote(note, null) assertEquals(note, fetchNote) diff --git a/hideout-core/src/test/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/ApNoteJobServiceImplTest.kt b/hideout-core/src/test/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/ApNoteJobServiceImplTest.kt deleted file mode 100644 index 43ce6003..00000000 --- a/hideout-core/src/test/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/ApNoteJobServiceImplTest.kt +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2024 usbharu - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") - -package dev.usbharu.hideout.activitypub.service.objects.note - -class ApNoteJobServiceImplTest { -// @Test -// fun `createPostJob 新しい投稿のJob`() = runTest { -// val apRequestService = mock() -// val user = UserBuilder.localUserOf() -// val userQueryService = mock { -// onBlocking { findByUrl(eq(user.url)) } doReturn user -// } -// val activityPubNoteService = ApNoteJobServiceImpl( -// -// userQueryService = userQueryService, -// apRequestService = apRequestService, -// objectMapper = JsonObjectMapper.objectMapper, -// transaction = TestTransaction -// ) -// val remoteUserOf = UserBuilder.remoteUserOf() -// activityPubNoteService.createNoteJob( -// JobProps( -// data = mapOf( -// DeliverPostJob.actor.name to user.url, -// DeliverPostJob.post.name to """{ -// "id": 1, -// "userId": ${user.id}, -// "text": "test text", -// "createdAt": 132525324, -// "visibility": 0, -// "url": "https://example.com" -// }""", -// DeliverPostJob.inbox.name to remoteUserOf.inbox, -// DeliverPostJob.media.name to "[]" -// ), json = Json -// ) -// ) -// -// val note = Note( -// name = "Note", -// id = "https://example.com", -// attributedTo = user.url, -// content = "test text", -// published = Instant.ofEpochMilli(132525324).toString(), -// to = listOfNotNull(APNoteServiceImpl.public, user.followers) -// ) -// val create = Create( -// name = "Create Note", -// `object` = note, -// actor = note.attributedTo, -// id = "https://example.com/create/note/1" -// ) -// verify(apRequestService, times(1)).apPost( -// eq(remoteUserOf.inbox), -// eq(create), -// eq(user) -// ) -// } -} diff --git a/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/service/user/ActorServiceTest.kt b/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/service/user/ActorServiceTest.kt index 834c3650..6a574dc6 100644 --- a/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/service/user/ActorServiceTest.kt +++ b/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/service/user/ActorServiceTest.kt @@ -18,18 +18,31 @@ package dev.usbharu.hideout.core.service.user +import dev.usbharu.hideout.activitypub.service.activity.delete.APSendDeleteService import dev.usbharu.hideout.application.config.ApplicationConfig import dev.usbharu.hideout.application.config.CharacterLimit import dev.usbharu.hideout.core.domain.model.actor.Actor import dev.usbharu.hideout.core.domain.model.actor.ActorRepository +import dev.usbharu.hideout.core.domain.model.deletedActor.DeletedActorRepository import dev.usbharu.hideout.core.domain.model.instance.Instance +import dev.usbharu.hideout.core.domain.model.post.PostRepository +import dev.usbharu.hideout.core.domain.model.reaction.ReactionRepository +import dev.usbharu.hideout.core.domain.model.relationship.RelationshipRepository +import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailRepository import dev.usbharu.hideout.core.service.instance.InstanceService +import dev.usbharu.hideout.core.service.post.PostService +import dev.usbharu.owl.producer.api.OwlProducer import jakarta.validation.Validation import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows +import org.junit.jupiter.api.extension.ExtendWith import org.mockito.ArgumentMatchers.anyString +import org.mockito.InjectMocks +import org.mockito.Mock +import org.mockito.Spy +import org.mockito.junit.jupiter.MockitoExtension import org.mockito.kotlin.* import utils.TestApplicationConfig.testApplicationConfig import java.net.URL @@ -38,40 +51,65 @@ import java.time.Instant import kotlin.test.assertEquals import kotlin.test.assertNull +@ExtendWith(MockitoExtension::class) class ActorServiceTest { - val actorBuilder = Actor.UserBuilder( + + @Mock + private lateinit var actorRepository: ActorRepository + + @Mock + private lateinit var userAuthService: UserAuthService + + @Spy + private val actorBuilder = Actor.UserBuilder( CharacterLimit(), ApplicationConfig(URL("https://example.com")), Validation.buildDefaultValidatorFactory().validator ) + @Spy + private val applicationConfig: ApplicationConfig = testApplicationConfig.copy(private = false) + + @Mock + private lateinit var instanceService: InstanceService + + @Mock + private lateinit var userDetailRepository: UserDetailRepository + + @Mock + private lateinit var deletedActorRepository: DeletedActorRepository + + @Mock + private lateinit var reactionRepository: ReactionRepository + + @Mock + private lateinit var relationshipRepository: RelationshipRepository + + @Mock + private lateinit var postService: PostService + + @Mock + private lateinit var apSendDeleteService: APSendDeleteService + + @Mock + private lateinit var postRepository: PostRepository + + @Mock + private lateinit var owlProducer: OwlProducer + + @InjectMocks + private lateinit var userService: UserServiceImpl + @Test fun `createLocalUser ローカルユーザーを作成できる`() = runTest { - val actorRepository = mock { - onBlocking { nextId() } doReturn 110001L - } val generateKeyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair() - val userAuthService = mock { - onBlocking { hash(anyString()) } doReturn "hashedPassword" - onBlocking { generateKeyPair() } doReturn generateKeyPair - } - val userService = - UserServiceImpl( - actorRepository = actorRepository, - userAuthService = userAuthService, - actorBuilder = actorBuilder, - applicationConfig = testApplicationConfig.copy(private = false), - instanceService = mock(), - userDetailRepository = mock(), - deletedActorRepository = mock(), - reactionRepository = mock(), - relationshipRepository = mock(), - postService = mock(), - apSendDeleteService = mock(), - postRepository = mock(), - owlProducer = mock() - ) + whenever(actorRepository.nextId()).doReturn(110001L) + whenever(userAuthService.hash(anyString())).doReturn("hashedPassword") + whenever(userAuthService.generateKeyPair()).doReturn(generateKeyPair) + + + userService.createLocalUser(UserCreateDto("test", "testUser", "XXXXXXXXXXXXX", "test")) verify(actorRepository, times(1)).save(any()) argumentCaptor { @@ -91,31 +129,7 @@ class ActorServiceTest { @Test fun `createLocalUser applicationconfig privateがtrueのときアカウントを作成できない`() = runTest { - - val actorRepository = mock { - onBlocking { nextId() } doReturn 110001L - } - val generateKeyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair() - val userAuthService = mock { - onBlocking { hash(anyString()) } doReturn "hashedPassword" - onBlocking { generateKeyPair() } doReturn generateKeyPair - } - val userService = - UserServiceImpl( - actorRepository = actorRepository, - userAuthService = userAuthService, - actorBuilder = actorBuilder, - applicationConfig = testApplicationConfig.copy(private = true), - instanceService = mock(), - userDetailRepository = mock(), - deletedActorRepository = mock(), - reactionRepository = mock(), - relationshipRepository = mock(), - postService = mock(), - apSendDeleteService = mock(), - postRepository = mock(), - owlProducer = mock() - ) + whenever(applicationConfig.private).thenReturn(true) assertThrows { userService.createLocalUser(UserCreateDto("test", "testUser", "XXXXXXXXXXXXX", "test")) @@ -126,17 +140,9 @@ class ActorServiceTest { @Test fun `createRemoteUser リモートユーザーを作成できる`() = runTest { - val actorRepository = mock { - onBlocking { nextId() } doReturn 113345L - } - - val instanceService = mock { - onBlocking { - fetchInstance( - eq("https://remote.example.com"), - isNull() - ) - } doReturn Instance( + whenever(actorRepository.nextId()).doReturn(113345L) + whenever(instanceService.fetchInstance(eq("https://remote.example.com"), isNull())).doReturn( + Instance( 12345L, "", "", @@ -150,23 +156,8 @@ class ActorServiceTest { "", Instant.now() ) - } - val userService = - UserServiceImpl( - actorRepository = actorRepository, - userAuthService = mock(), - actorBuilder = actorBuilder, - applicationConfig = testApplicationConfig, - instanceService = instanceService, - userDetailRepository = mock(), - deletedActorRepository = mock(), - reactionRepository = mock(), - relationshipRepository = mock(), - postService = mock(), - apSendDeleteService = mock(), - postRepository = mock(), - owlProducer = mock() - ) + ) + val user = RemoteUserCreateDto( name = "test", domain = "remote.example.com",