diff --git a/mirai-core-mock/src/MockBot.kt b/mirai-core-mock/src/MockBot.kt
index bf6a98c8b..7e835ce15 100644
--- a/mirai-core-mock/src/MockBot.kt
+++ b/mirai-core-mock/src/MockBot.kt
@@ -24,6 +24,7 @@ import net.mamoe.mirai.mock.contact.*
 import net.mamoe.mirai.mock.database.MessageDatabase
 import net.mamoe.mirai.mock.resserver.TmpResourceServer
 import net.mamoe.mirai.mock.userprofile.UserProfileService
+import net.mamoe.mirai.mock.utils.AvatarGenerator
 import net.mamoe.mirai.mock.utils.NameGenerator
 import net.mamoe.mirai.utils.ExternalResource
 import net.mamoe.mirai.utils.cast
@@ -86,6 +87,9 @@ public interface MockBot : Bot, MockContactOrBot, MockUserOrBot {
     public val msgDatabase: MessageDatabase
     public val userProfileService: UserProfileService
 
+    /** @since 2.14.0 */
+    public val avatarGenerator: AvatarGenerator
+
     /// Mock Contact API
 
     @MockBotDSL
diff --git a/mirai-core-mock/src/MockBotFactory.kt b/mirai-core-mock/src/MockBotFactory.kt
index 05079357a..71e2e862d 100644
--- a/mirai-core-mock/src/MockBotFactory.kt
+++ b/mirai-core-mock/src/MockBotFactory.kt
@@ -16,6 +16,7 @@ import net.mamoe.mirai.mock.internal.MockBotFactoryImpl
 import net.mamoe.mirai.mock.internal.MockMiraiImpl
 import net.mamoe.mirai.mock.resserver.TmpResourceServer
 import net.mamoe.mirai.mock.userprofile.UserProfileService
+import net.mamoe.mirai.mock.utils.AvatarGenerator
 import net.mamoe.mirai.mock.utils.NameGenerator
 import net.mamoe.mirai.utils.BotConfiguration
 
@@ -36,6 +37,8 @@ public interface MockBotFactory : BotFactory {
 
         public fun userProfileService(service: UserProfileService): BotBuilder
 
+        public fun avatarGenerator(avatarGenerator: AvatarGenerator): BotBuilder
+
         public fun create(): MockBot
 
         public fun createNoInstanceRegister(): MockBot
diff --git a/mirai-core-mock/src/internal/MockBotFactoryImpl.kt b/mirai-core-mock/src/internal/MockBotFactoryImpl.kt
index 10eec38c3..26a76517d 100644
--- a/mirai-core-mock/src/internal/MockBotFactoryImpl.kt
+++ b/mirai-core-mock/src/internal/MockBotFactoryImpl.kt
@@ -10,12 +10,15 @@
 package net.mamoe.mirai.mock.internal
 
 import net.mamoe.mirai.Bot
+import net.mamoe.mirai.message.data.Image
 import net.mamoe.mirai.mock.MockBot
 import net.mamoe.mirai.mock.MockBotFactory
 import net.mamoe.mirai.mock.database.MessageDatabase
 import net.mamoe.mirai.mock.resserver.TmpResourceServer
 import net.mamoe.mirai.mock.userprofile.UserProfileService
+import net.mamoe.mirai.mock.utils.AvatarGenerator
 import net.mamoe.mirai.mock.utils.NameGenerator
+import net.mamoe.mirai.mock.utils.randomImageContent
 import net.mamoe.mirai.utils.BotConfiguration
 import net.mamoe.mirai.utils.lateinitMutableProperty
 import kotlin.math.absoluteValue
@@ -39,6 +42,11 @@ internal class MockBotFactoryImpl : MockBotFactory {
             var userProfileService: UserProfileService by lateinitMutableProperty {
                 UserProfileService.getInstance()
             }
+            var avatarGenerator: AvatarGenerator by lateinitMutableProperty {
+                object : AvatarGenerator {
+                    override fun generateRandomAvatar(): ByteArray = Image.randomImageContent()
+                }
+            }
 
             override fun id(value: Long): MockBotFactory.BotBuilder = apply {
                 this.id = value
@@ -68,6 +76,10 @@ internal class MockBotFactoryImpl : MockBotFactory {
                 userProfileService = service
             }
 
+            override fun avatarGenerator(avatarGenerator: AvatarGenerator): MockBotFactory.BotBuilder = apply {
+                this.avatarGenerator = avatarGenerator
+            }
+
             override fun createNoInstanceRegister(): MockBot {
                 return MockBotImpl(
                     configuration_,
@@ -77,6 +89,7 @@ internal class MockBotFactoryImpl : MockBotFactory {
                     tmpResourceServer_,
                     msgDb,
                     userProfileService,
+                    avatarGenerator,
                 )
             }
 
diff --git a/mirai-core-mock/src/internal/MockBotImpl.kt b/mirai-core-mock/src/internal/MockBotImpl.kt
index e665a0327..df36f7956 100644
--- a/mirai-core-mock/src/internal/MockBotImpl.kt
+++ b/mirai-core-mock/src/internal/MockBotImpl.kt
@@ -43,6 +43,7 @@ import net.mamoe.mirai.mock.internal.contactbase.ContactDatabase
 import net.mamoe.mirai.mock.internal.serverfs.TmpResourceServerImpl
 import net.mamoe.mirai.mock.resserver.TmpResourceServer
 import net.mamoe.mirai.mock.userprofile.UserProfileService
+import net.mamoe.mirai.mock.utils.AvatarGenerator
 import net.mamoe.mirai.mock.utils.NameGenerator
 import net.mamoe.mirai.mock.utils.simpleMemberInfo
 import net.mamoe.mirai.utils.*
@@ -60,6 +61,7 @@ internal class MockBotImpl(
     override val tmpResourceServer: TmpResourceServer,
     override val msgDatabase: MessageDatabase,
     override val userProfileService: UserProfileService,
+    override val avatarGenerator: AvatarGenerator,
 ) : MockBot, Bot, ContactOrBot {
     @JvmField
     internal val contactDatabase = ContactDatabase(this)
diff --git a/mirai-core-mock/src/internal/contact/MockGroupImpl.kt b/mirai-core-mock/src/internal/contact/MockGroupImpl.kt
index 60649cebb..465e213e6 100644
--- a/mirai-core-mock/src/internal/contact/MockGroupImpl.kt
+++ b/mirai-core-mock/src/internal/contact/MockGroupImpl.kt
@@ -229,7 +229,7 @@ internal class MockGroupImpl(
 
     override val mockApi: MockGroup.MockApi = object : MockGroup.MockApi {
         override var avatarUrl: String by lateinitMutableProperty {
-            runBlocking { MockImage.random(bot).getUrl(bot) }
+            runBlocking { MockImage.randomForGroup(bot, id).getUrl(bot) }
         }
     }
 
diff --git a/mirai-core-mock/src/internal/contact/util.kt b/mirai-core-mock/src/internal/contact/util.kt
index ad8123a0d..6a57cd83f 100644
--- a/mirai-core-mock/src/internal/contact/util.kt
+++ b/mirai-core-mock/src/internal/contact/util.kt
@@ -24,7 +24,6 @@ import net.mamoe.mirai.mock.MockBot
 import net.mamoe.mirai.mock.contact.MockGroup
 import net.mamoe.mirai.mock.utils.mock
 import net.mamoe.mirai.mock.utils.plusHttpSubpath
-import net.mamoe.mirai.mock.utils.randomImageContent
 import net.mamoe.mirai.utils.ExternalResource
 import net.mamoe.mirai.utils.ExternalResource.Companion.toExternalResource
 import net.mamoe.mirai.utils.cast
@@ -110,7 +109,17 @@ internal class MockImage(
     companion object {
         // create a mockImage with random content
         internal suspend fun random(bot: MockBot): MockImage {
-            val text = Image.randomImageContent()
+            val text = bot.avatarGenerator.generateRandomAvatar()
+            return bot.uploadMockImage(text.toExternalResource().toAutoCloseable()).cast()
+        }
+
+        internal suspend fun randomForPerson(bot: MockBot, id: Long): MockImage {
+            val text = bot.avatarGenerator.generateAvatarForPerson(id)
+            return bot.uploadMockImage(text.toExternalResource().toAutoCloseable()).cast()
+        }
+
+        internal suspend fun randomForGroup(bot: MockBot, id: Long): MockImage {
+            val text = bot.avatarGenerator.generateAvatarForGroup(id)
             return bot.uploadMockImage(text.toExternalResource().toAutoCloseable()).cast()
         }
     }
diff --git a/mirai-core-mock/src/internal/contactbase/ContactInfo.kt b/mirai-core-mock/src/internal/contactbase/ContactInfo.kt
index 385ca8450..a9ca5bda4 100644
--- a/mirai-core-mock/src/internal/contactbase/ContactInfo.kt
+++ b/mirai-core-mock/src/internal/contactbase/ContactInfo.kt
@@ -25,7 +25,7 @@ internal class ContactInfo(
     @JvmField var nick: String,
 ) {
     var avatarUrl: String by lateinitMutableProperty {
-        runBlocking { MockImage.random(declaredBot).getUrl(declaredBot) }
+        runBlocking { MockImage.randomForPerson(declaredBot, id).getUrl(declaredBot) }
     }
 
     fun changeAvatarUrl(newAvatar: String) {
diff --git a/mirai-core-mock/src/utils/AvatarGenerator.kt b/mirai-core-mock/src/utils/AvatarGenerator.kt
new file mode 100644
index 000000000..499299e5b
--- /dev/null
+++ b/mirai-core-mock/src/utils/AvatarGenerator.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2019-2022 Mamoe Technologies and contributors.
+ *
+ * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
+ * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
+ *
+ * https://github.com/mamoe/mirai/blob/dev/LICENSE
+ */
+
+package net.mamoe.mirai.mock.utils
+
+/**
+ * 头像生成器
+ *
+ * @since 2.14.0
+ */
+public interface AvatarGenerator {
+    public fun generateAvatarForPerson(id: Long): ByteArray = generateRandomAvatar()
+    public fun generateAvatarForGroup(id: Long): ByteArray = generateRandomAvatar()
+
+    public fun generateRandomAvatar(): ByteArray
+}