Files
Wino-Mail/Wino.Core.Tests/Services/LegacyLocalMigrationServiceTests.cs
T
Burak Kaan Köse c1bda75d9f Migration plan v1
2026-04-23 14:52:52 +02:00

697 lines
29 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using FluentAssertions;
using Moq;
using SQLite;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Tests.Helpers;
using Wino.Services;
using Xunit;
namespace Wino.Core.Tests.Services;
public sealed class LegacyLocalMigrationServiceTests
{
[Fact]
public async Task DetectAsync_ReturnsPreviewCountsAndDuplicatesByProvider()
{
await using var context = await LegacyMigrationTestContext.CreateAsync();
await context.SeedCurrentAccountAsync(
"gmail@example.com",
MailProviderType.Gmail,
"Existing Gmail");
await context.InsertLegacyAccountAsync(
Guid.NewGuid(),
"outlook@example.com",
MailProviderType.Outlook,
order: 0,
name: "Outlook Legacy");
await context.InsertLegacyAccountAsync(
Guid.NewGuid(),
"gmail@example.com",
MailProviderType.Gmail,
order: 1,
name: "Duplicate Gmail");
var imapId = Guid.NewGuid();
await context.InsertLegacyAccountAsync(
imapId,
"imap@example.com",
MailProviderType.IMAP4,
order: 2,
name: "Imported IMAP",
specialImapProvider: SpecialImapProvider.Yahoo);
await context.InsertLegacyServerInformationAsync(
imapId,
address: "imap@example.com",
incomingServer: "imap.mail.yahoo.com",
incomingServerPort: "993",
incomingServerUsername: "imap@example.com",
outgoingServer: "smtp.mail.yahoo.com",
outgoingServerPort: "587",
outgoingServerUsername: "imap@example.com",
calendarSupportMode: ImapCalendarSupportMode.CalDav,
calDavServiceUrl: "https://caldav.calendar.yahoo.com/",
calDavUsername: "imap@example.com");
var preview = await context.Service.DetectAsync();
preview.LegacyDatabaseExists.Should().BeTrue();
preview.ShouldPrompt.Should().BeTrue();
preview.LegacyAccountCount.Should().Be(3);
preview.ImportableAccountCount.Should().Be(2);
preview.DuplicateAccountCount.Should().Be(1);
preview.Accounts.Select(a => a.Address).Should().ContainInOrder(
"outlook@example.com",
"gmail@example.com",
"imap@example.com");
preview.ProviderCounts.Should().ContainSingle(a =>
a.ProviderType == MailProviderType.Outlook &&
a.ImportableAccountCount == 1 &&
a.DuplicateAccountCount == 0);
preview.ProviderCounts.Should().ContainSingle(a =>
a.ProviderType == MailProviderType.Gmail &&
a.ImportableAccountCount == 0 &&
a.DuplicateAccountCount == 1);
preview.ProviderCounts.Should().ContainSingle(a =>
a.ProviderType == MailProviderType.IMAP4 &&
a.ImportableAccountCount == 1 &&
a.DuplicateAccountCount == 0);
}
[Fact]
public async Task ImportAsync_ImportsAccountsPreservesSafePreferencesAndRecreatesMergedInboxes()
{
await using var context = await LegacyMigrationTestContext.CreateAsync();
var mergedInboxId = Guid.NewGuid();
await context.InsertLegacyMergedInboxAsync(mergedInboxId, "Legacy Linked");
var legacyOutlookId = Guid.NewGuid();
var legacyGmailId = Guid.NewGuid();
var legacyImapId = Guid.NewGuid();
var legacySignatureId = Guid.NewGuid();
await context.InsertLegacyAccountAsync(
legacyOutlookId,
"outlook@example.com",
MailProviderType.Outlook,
order: 0,
name: "Outlook Legacy",
senderName: "Outlook Sender",
mergedInboxId: mergedInboxId);
await context.InsertLegacyPreferencesAsync(
legacyOutlookId,
isNotificationsEnabled: false,
isTaskbarBadgeEnabled: false,
shouldAppendMessagesToSentFolder: true,
isFocusedInboxEnabled: false,
signatureIdForNewMessages: legacySignatureId,
signatureIdForFollowingMessages: legacySignatureId);
await context.InsertLegacyAccountAsync(
legacyGmailId,
"gmail@example.com",
MailProviderType.Gmail,
order: 1,
name: "Gmail Legacy",
senderName: "Gmail Sender",
mergedInboxId: mergedInboxId);
await context.InsertLegacyAccountAsync(
legacyImapId,
"imap@example.com",
MailProviderType.IMAP4,
order: 2,
name: "iCloud Legacy",
senderName: "iCloud Sender",
specialImapProvider: SpecialImapProvider.iCloud);
await context.InsertLegacyServerInformationAsync(
legacyImapId,
address: "imap@example.com",
incomingServer: "imap.mail.me.com",
incomingServerPort: "993",
incomingServerUsername: "imap-user",
outgoingServer: "smtp.mail.me.com",
outgoingServerPort: "587",
outgoingServerUsername: "smtp-user",
calendarSupportMode: ImapCalendarSupportMode.CalDav,
calDavServiceUrl: "https://caldav.icloud.com/",
calDavUsername: "imap@example.com",
maxConcurrentClients: 7);
var result = await context.Service.ImportAsync();
result.ImportedAccountCount.Should().Be(3);
result.SkippedDuplicateAccountCount.Should().Be(0);
result.FailedAccountCount.Should().Be(0);
result.ImportedMergedInboxCount.Should().Be(1);
result.SkippedMergedInboxCount.Should().Be(0);
var accounts = await context.AccountService.GetAccountsAsync();
accounts.Should().HaveCount(3);
accounts.Select(a => a.Address).Should().ContainInOrder(
"outlook@example.com",
"gmail@example.com",
"imap@example.com");
var outlookAccount = accounts.Single(a => a.Address == "outlook@example.com");
outlookAccount.AttentionReason.Should().Be(AccountAttentionReason.InvalidCredentials);
outlookAccount.IsMailAccessGranted.Should().BeTrue();
outlookAccount.IsCalendarAccessGranted.Should().BeTrue();
outlookAccount.Preferences.IsNotificationsEnabled.Should().BeFalse();
outlookAccount.Preferences.IsTaskbarBadgeEnabled.Should().BeFalse();
outlookAccount.Preferences.ShouldAppendMessagesToSentFolder.Should().BeTrue();
outlookAccount.Preferences.IsFocusedInboxEnabled.Should().BeFalse();
outlookAccount.Preferences.SignatureIdForNewMessages.Should().NotBe(legacySignatureId);
outlookAccount.Preferences.SignatureIdForFollowingMessages.Should().NotBe(legacySignatureId);
var gmailAliases = await context.AccountService.GetAccountAliasesAsync(accounts.Single(a => a.Address == "gmail@example.com").Id);
gmailAliases.Should().ContainSingle(a =>
a.IsRootAlias &&
a.IsPrimary &&
a.AliasAddress == "gmail@example.com");
var imapAccount = accounts.Single(a => a.Address == "imap@example.com");
imapAccount.AttentionReason.Should().Be(AccountAttentionReason.InvalidCredentials);
imapAccount.IsCalendarAccessGranted.Should().BeTrue();
var serverInformation = await context.AccountService.GetAccountCustomServerInformationAsync(imapAccount.Id);
serverInformation.Should().NotBeNull();
serverInformation.IncomingServer.Should().Be("imap.mail.me.com");
serverInformation.OutgoingServer.Should().Be("smtp.mail.me.com");
serverInformation.IncomingServerPassword.Should().BeEmpty();
serverInformation.OutgoingServerPassword.Should().BeEmpty();
serverInformation.CalDavPassword.Should().BeEmpty();
serverInformation.CalDavServiceUrl.Should().Be("https://caldav.icloud.com/");
serverInformation.CalDavUsername.Should().Be("imap@example.com");
serverInformation.MaxConcurrentClients.Should().Be(7);
var mergedInboxIds = accounts
.Where(a => a.Address is "outlook@example.com" or "gmail@example.com")
.Select(a => a.MergedInboxId)
.Distinct()
.ToList();
mergedInboxIds.Should().ContainSingle();
mergedInboxIds[0].Should().NotBeNull();
accounts.Single(a => a.Address == "outlook@example.com").MergedInbox.Name.Should().Be("Legacy Linked");
}
[Fact]
public async Task ImportAsync_WithMissingLegacySchemaColumns_DefaultsSafelyAndSkipsIncompleteMergedInboxes()
{
await using var context = await LegacyMigrationTestContext.CreateAsync(new LegacySchemaOptions(
IncludeCalDavColumns: false,
IncludeCalendarSupportMode: false,
IncludeTaskbarBadgeColumn: false,
IncludeFocusedInboxColumn: false));
await context.SeedCurrentAccountAsync(
"duplicate@icloud.com",
MailProviderType.IMAP4,
"Existing iCloud",
specialImapProvider: SpecialImapProvider.iCloud);
var mergedInboxId = Guid.NewGuid();
var duplicateLegacyAccountId = Guid.NewGuid();
var importableLegacyAccountId = Guid.NewGuid();
await context.InsertLegacyMergedInboxAsync(mergedInboxId, "Legacy Incomplete");
await context.InsertLegacyAccountAsync(
duplicateLegacyAccountId,
"duplicate@icloud.com",
MailProviderType.IMAP4,
order: 0,
name: "Duplicate iCloud",
specialImapProvider: SpecialImapProvider.iCloud,
mergedInboxId: mergedInboxId);
await context.InsertLegacyAccountAsync(
importableLegacyAccountId,
"new@icloud.com",
MailProviderType.IMAP4,
order: 1,
name: "Importable iCloud",
specialImapProvider: SpecialImapProvider.iCloud,
mergedInboxId: mergedInboxId);
await context.InsertLegacyServerInformationAsync(
duplicateLegacyAccountId,
address: "duplicate@icloud.com",
incomingServer: "imap.mail.me.com",
incomingServerPort: "993",
incomingServerUsername: "duplicate",
outgoingServer: "smtp.mail.me.com",
outgoingServerPort: "587",
outgoingServerUsername: "duplicate");
await context.InsertLegacyServerInformationAsync(
importableLegacyAccountId,
address: "new@icloud.com",
incomingServer: "imap.mail.me.com",
incomingServerPort: "993",
incomingServerUsername: "new",
outgoingServer: "smtp.mail.me.com",
outgoingServerPort: "587",
outgoingServerUsername: "new");
var result = await context.Service.ImportAsync();
result.ImportedAccountCount.Should().Be(1);
result.SkippedDuplicateAccountCount.Should().Be(1);
result.ImportedMergedInboxCount.Should().Be(0);
result.SkippedMergedInboxCount.Should().Be(1);
var importedAccount = (await context.AccountService.GetAccountsAsync())
.Single(a => a.Address == "new@icloud.com");
importedAccount.IsCalendarAccessGranted.Should().BeFalse();
importedAccount.MergedInboxId.Should().BeNull();
importedAccount.AttentionReason.Should().Be(AccountAttentionReason.InvalidCredentials);
var importedServerInfo = await context.AccountService.GetAccountCustomServerInformationAsync(importedAccount.Id);
importedServerInfo.Should().NotBeNull();
importedServerInfo.CalDavServiceUrl.Should().Be("https://caldav.icloud.com/");
importedServerInfo.CalDavUsername.Should().Be("new@icloud.com");
importedServerInfo.CalDavPassword.Should().BeEmpty();
importedServerInfo.CalendarSupportMode.Should().Be(ImapCalendarSupportMode.Disabled);
importedServerInfo.IncomingServerPassword.Should().BeEmpty();
importedServerInfo.OutgoingServerPassword.Should().BeEmpty();
}
private sealed class LegacyMigrationTestContext : IAsyncDisposable
{
private readonly SQLiteAsyncConnection _legacyConnection;
private readonly InMemoryDatabaseService _databaseService;
private readonly string _legacyFolderPath;
public LegacyLocalMigrationService Service { get; }
public AccountService AccountService { get; }
private LegacyMigrationTestContext(string legacyFolderPath,
SQLiteAsyncConnection legacyConnection,
InMemoryDatabaseService databaseService,
AccountService accountService,
LegacyLocalMigrationService service)
{
_legacyFolderPath = legacyFolderPath;
_legacyConnection = legacyConnection;
_databaseService = databaseService;
AccountService = accountService;
Service = service;
}
public static async Task<LegacyMigrationTestContext> CreateAsync(LegacySchemaOptions? schemaOptions = null)
{
var databaseService = new InMemoryDatabaseService();
await databaseService.InitializeAsync();
var preferencesService = new Mock<IPreferencesService>();
preferencesService.SetupProperty(a => a.StartupEntityId);
var accountService = CreateAccountService(databaseService, preferencesService.Object);
var legacyFolderPath = Path.Combine(Path.GetTempPath(), $"legacy-migration-tests-{Guid.NewGuid():N}");
Directory.CreateDirectory(legacyFolderPath);
var legacyDatabasePath = Path.Combine(legacyFolderPath, "Wino180.db");
var legacyConnection = new SQLiteAsyncConnection(legacyDatabasePath);
await CreateLegacySchemaAsync(legacyConnection, schemaOptions ?? LegacySchemaOptions.Default);
var applicationConfiguration = new ApplicationConfiguration
{
ApplicationDataFolderPath = legacyFolderPath,
ApplicationTempFolderPath = legacyFolderPath,
PublisherSharedFolderPath = legacyFolderPath
};
var service = new LegacyLocalMigrationService(
applicationConfiguration,
new InMemoryConfigurationService(),
databaseService,
accountService,
new SpecialImapProviderConfigResolver());
return new LegacyMigrationTestContext(
legacyFolderPath,
legacyConnection,
databaseService,
accountService,
service);
}
public async Task SeedCurrentAccountAsync(string address,
MailProviderType providerType,
string name,
SpecialImapProvider specialImapProvider = SpecialImapProvider.None)
{
var accountId = Guid.NewGuid();
CustomServerInformation? serverInformation = null;
if (providerType == MailProviderType.IMAP4)
{
serverInformation = new CustomServerInformation
{
Id = Guid.NewGuid(),
AccountId = accountId,
Address = address,
IncomingServer = "imap.current.test",
IncomingServerPort = "993",
IncomingServerUsername = address,
IncomingServerPassword = "secret",
IncomingServerSocketOption = ImapConnectionSecurity.Auto,
IncomingAuthenticationMethod = ImapAuthenticationMethod.NormalPassword,
OutgoingServer = "smtp.current.test",
OutgoingServerPort = "587",
OutgoingServerUsername = address,
OutgoingServerPassword = "secret",
OutgoingServerSocketOption = ImapConnectionSecurity.Auto,
OutgoingAuthenticationMethod = ImapAuthenticationMethod.NormalPassword,
CalDavServiceUrl = string.Empty,
CalDavUsername = string.Empty,
CalDavPassword = string.Empty,
CalendarSupportMode = ImapCalendarSupportMode.Disabled,
MaxConcurrentClients = 5
};
}
await AccountService.CreateAccountAsync(
new MailAccount
{
Id = accountId,
Name = name,
SenderName = name,
Address = address,
ProviderType = providerType,
SpecialImapProvider = specialImapProvider,
IsMailAccessGranted = true,
IsCalendarAccessGranted = providerType is MailProviderType.Outlook or MailProviderType.Gmail
},
serverInformation);
}
public Task InsertLegacyAccountAsync(Guid accountId,
string address,
MailProviderType providerType,
int order,
string name,
string? senderName = null,
SpecialImapProvider specialImapProvider = SpecialImapProvider.None,
Guid? mergedInboxId = null)
=> InsertRowAsync(
_legacyConnection,
"MailAccount",
("Id", accountId),
("Address", address),
("Name", name),
("SenderName", senderName ?? name),
("ProviderType", (int)providerType),
("SpecialImapProvider", (int)specialImapProvider),
("Order", order),
("AccountColorHex", "#123456"),
("MergedInboxId", mergedInboxId));
public Task InsertLegacyPreferencesAsync(Guid accountId,
bool? isNotificationsEnabled = null,
bool? isTaskbarBadgeEnabled = null,
bool? shouldAppendMessagesToSentFolder = null,
bool? isFocusedInboxEnabled = null,
Guid? signatureIdForNewMessages = null,
Guid? signatureIdForFollowingMessages = null)
{
var values = new List<(string Column, object? Value)>
{
("Id", Guid.NewGuid()),
("AccountId", accountId)
};
if (isNotificationsEnabled.HasValue)
values.Add(("IsNotificationsEnabled", isNotificationsEnabled.Value));
if (isTaskbarBadgeEnabled.HasValue)
values.Add(("IsTaskbarBadgeEnabled", isTaskbarBadgeEnabled.Value));
if (shouldAppendMessagesToSentFolder.HasValue)
values.Add(("ShouldAppendMessagesToSentFolder", shouldAppendMessagesToSentFolder.Value));
if (isFocusedInboxEnabled.HasValue)
values.Add(("IsFocusedInboxEnabled", isFocusedInboxEnabled.Value));
if (signatureIdForNewMessages.HasValue)
values.Add(("SignatureIdForNewMessages", signatureIdForNewMessages.Value));
if (signatureIdForFollowingMessages.HasValue)
values.Add(("SignatureIdForFollowingMessages", signatureIdForFollowingMessages.Value));
return InsertRowAsync(_legacyConnection, "MailAccountPreferences", values.ToArray());
}
public Task InsertLegacyServerInformationAsync(Guid accountId,
string address,
string incomingServer,
string incomingServerPort,
string incomingServerUsername,
string outgoingServer,
string outgoingServerPort,
string outgoingServerUsername,
ImapCalendarSupportMode? calendarSupportMode = null,
string? calDavServiceUrl = null,
string? calDavUsername = null,
int? maxConcurrentClients = null)
{
var values = new List<(string Column, object? Value)>
{
("Id", Guid.NewGuid()),
("AccountId", accountId),
("Address", address),
("IncomingServer", incomingServer),
("IncomingServerPort", incomingServerPort),
("IncomingServerUsername", incomingServerUsername),
("IncomingServerSocketOption", (int)ImapConnectionSecurity.Auto),
("IncomingAuthenticationMethod", (int)ImapAuthenticationMethod.NormalPassword),
("OutgoingServer", outgoingServer),
("OutgoingServerPort", outgoingServerPort),
("OutgoingServerUsername", outgoingServerUsername),
("OutgoingServerSocketOption", (int)ImapConnectionSecurity.Auto),
("OutgoingAuthenticationMethod", (int)ImapAuthenticationMethod.NormalPassword),
("ProxyServer", "proxy.example.com"),
("ProxyServerPort", "8080"),
("MaxConcurrentClients", maxConcurrentClients ?? 5)
};
if (calendarSupportMode.HasValue)
values.Add(("CalendarSupportMode", (int)calendarSupportMode.Value));
if (!string.IsNullOrWhiteSpace(calDavServiceUrl))
values.Add(("CalDavServiceUrl", calDavServiceUrl));
if (!string.IsNullOrWhiteSpace(calDavUsername))
values.Add(("CalDavUsername", calDavUsername));
return InsertRowAsync(_legacyConnection, "CustomServerInformation", values.ToArray());
}
public Task InsertLegacyMergedInboxAsync(Guid mergedInboxId, string name)
=> InsertRowAsync(
_legacyConnection,
"MergedInbox",
("Id", mergedInboxId),
("Name", name));
public async ValueTask DisposeAsync()
{
await _legacyConnection.CloseAsync();
if (Directory.Exists(_legacyFolderPath))
{
Directory.Delete(_legacyFolderPath, recursive: true);
}
await _databaseService.DisposeAsync();
}
}
private sealed class InMemoryConfigurationService : IConfigurationService
{
private readonly Dictionary<string, string?> _localValues = new(StringComparer.Ordinal);
private readonly Dictionary<string, string?> _roamingValues = new(StringComparer.Ordinal);
public bool Contains(string key) => _localValues.ContainsKey(key);
public T Get<T>(string key, T defaultValue = default!)
=> TryGetValue(_localValues, key, defaultValue);
public T GetRoaming<T>(string key, T defaultValue = default!)
=> TryGetValue(_roamingValues, key, defaultValue);
public void Set(string key, object value)
=> _localValues[key] = value?.ToString();
public void SetRoaming(string key, object value)
=> _roamingValues[key] = value?.ToString();
private static T TryGetValue<T>(Dictionary<string, string?> values, string key, T defaultValue)
{
if (!values.TryGetValue(key, out var stringValue) || string.IsNullOrWhiteSpace(stringValue))
{
return defaultValue;
}
if (typeof(T).IsEnum)
{
return (T)Enum.Parse(typeof(T), stringValue);
}
if ((typeof(T) == typeof(Guid) || typeof(T) == typeof(Guid?)) && Guid.TryParse(stringValue, out var guid))
{
return (T)(object)guid;
}
return (T)Convert.ChangeType(stringValue, typeof(T));
}
}
private sealed record LegacySchemaOptions(
bool IncludeCalDavColumns,
bool IncludeCalendarSupportMode,
bool IncludeTaskbarBadgeColumn,
bool IncludeFocusedInboxColumn)
{
public static LegacySchemaOptions Default => new(true, true, true, true);
}
private static async Task CreateLegacySchemaAsync(SQLiteAsyncConnection connection, LegacySchemaOptions options)
{
await connection.ExecuteAsync("""
CREATE TABLE MailAccount (
Id TEXT PRIMARY KEY,
Address TEXT NULL,
Name TEXT NULL,
SenderName TEXT NULL,
ProviderType INTEGER NOT NULL,
SpecialImapProvider INTEGER NOT NULL DEFAULT 0,
[Order] INTEGER NOT NULL DEFAULT 0,
AccountColorHex TEXT NULL,
MergedInboxId TEXT NULL
)
""");
var preferenceColumns = new List<string>
{
"Id TEXT PRIMARY KEY",
"AccountId TEXT NOT NULL",
"IsNotificationsEnabled INTEGER NULL",
"ShouldAppendMessagesToSentFolder INTEGER NULL",
"SignatureIdForNewMessages TEXT NULL",
"SignatureIdForFollowingMessages TEXT NULL"
};
if (options.IncludeTaskbarBadgeColumn)
preferenceColumns.Add("IsTaskbarBadgeEnabled INTEGER NULL");
if (options.IncludeFocusedInboxColumn)
preferenceColumns.Add("IsFocusedInboxEnabled INTEGER NULL");
await connection.ExecuteAsync($"CREATE TABLE MailAccountPreferences ({string.Join(", ", preferenceColumns)})");
var serverColumns = new List<string>
{
"Id TEXT PRIMARY KEY",
"AccountId TEXT NOT NULL",
"Address TEXT NULL",
"IncomingServer TEXT NULL",
"IncomingServerPort TEXT NULL",
"IncomingServerUsername TEXT NULL",
"IncomingServerSocketOption INTEGER NULL",
"IncomingAuthenticationMethod INTEGER NULL",
"OutgoingServer TEXT NULL",
"OutgoingServerPort TEXT NULL",
"OutgoingServerUsername TEXT NULL",
"OutgoingServerSocketOption INTEGER NULL",
"OutgoingAuthenticationMethod INTEGER NULL",
"ProxyServer TEXT NULL",
"ProxyServerPort TEXT NULL",
"MaxConcurrentClients INTEGER NULL"
};
if (options.IncludeCalDavColumns)
{
serverColumns.Add("CalDavServiceUrl TEXT NULL");
serverColumns.Add("CalDavUsername TEXT NULL");
}
if (options.IncludeCalendarSupportMode)
{
serverColumns.Add("CalendarSupportMode INTEGER NULL");
}
await connection.ExecuteAsync($"CREATE TABLE CustomServerInformation ({string.Join(", ", serverColumns)})");
await connection.ExecuteAsync("""
CREATE TABLE MergedInbox (
Id TEXT PRIMARY KEY,
Name TEXT NULL
)
""");
}
private static Task InsertRowAsync(SQLiteAsyncConnection connection, string tableName, params (string Column, object? Value)[] values)
{
var columns = string.Join(", ", values.Select(a => $"[{a.Column}]"));
var placeholders = string.Join(", ", values.Select(_ => "?"));
var arguments = values.Select(a => ConvertLegacyValue(a.Value)).ToArray();
return connection.ExecuteAsync($"INSERT INTO [{tableName}] ({columns}) VALUES ({placeholders})", arguments);
}
private static object? ConvertLegacyValue(object? value)
{
return value switch
{
null => null,
bool boolValue => boolValue ? 1 : 0,
Guid guidValue => guidValue.ToString(),
_ => value
};
}
private static AccountService CreateAccountService(InMemoryDatabaseService databaseService, IPreferencesService preferencesService)
{
var signatureService = new Mock<ISignatureService>();
signatureService
.Setup(a => a.CreateDefaultSignatureAsync(It.IsAny<Guid>()))
.ReturnsAsync((Guid accountId) => new AccountSignature
{
Id = Guid.NewGuid(),
MailAccountId = accountId,
Name = "Default",
HtmlBody = string.Empty
});
return new AccountService(
databaseService,
signatureService.Object,
Mock.Of<IAuthenticationProvider>(),
Mock.Of<IMimeFileService>(),
preferencesService,
Mock.Of<IContactPictureFileService>());
}
}