Added tests
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
using FluentAssertions;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Xunit;
|
||||
|
||||
namespace Musify.Application.Tests.Infrastructure;
|
||||
|
||||
public sealed class SchemaSmokeTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task Schema_creates_and_persists_all_core_entities()
|
||||
{
|
||||
await using var ctx = new SqliteTestContext();
|
||||
|
||||
var user = TestData.User();
|
||||
ctx.Database.Users.Add(user);
|
||||
ctx.Database.UploadIntents.Add(TestData.UploadIntent(user.Id));
|
||||
ctx.Database.PlayLists.Add(TestData.PlayList(user.Id));
|
||||
await ctx.Database.SaveChangesAsync(CancellationToken.None);
|
||||
|
||||
var verify = ctx.NewContext();
|
||||
(await verify.Users.CountAsync()).Should().Be(1);
|
||||
(await verify.UploadIntents.CountAsync()).Should().Be(1);
|
||||
(await verify.PlayLists.CountAsync()).Should().Be(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Transactions_are_supported_under_sqlite()
|
||||
{
|
||||
await using var ctx = new SqliteTestContext();
|
||||
var user = TestData.User();
|
||||
|
||||
await using (var tx = await ctx.Database.BeginTransactionAsync(
|
||||
System.Data.IsolationLevel.Serializable, CancellationToken.None))
|
||||
{
|
||||
ctx.Database.Users.Add(user);
|
||||
await ctx.Database.SaveChangesAsync(CancellationToken.None);
|
||||
await tx.CommitAsync(CancellationToken.None);
|
||||
}
|
||||
|
||||
(await ctx.NewContext().Users.CountAsync()).Should().Be(1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using Microsoft.Data.Sqlite;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Musify.Application.Tests.Infrastructure;
|
||||
|
||||
public sealed class SqliteTestContext : IAsyncDisposable, IDisposable
|
||||
{
|
||||
private readonly SqliteConnection _connection;
|
||||
|
||||
public TestDatabase Database { get; }
|
||||
|
||||
public SqliteTestContext()
|
||||
{
|
||||
_connection = new SqliteConnection("DataSource=:memory:;Foreign Keys=False");
|
||||
_connection.Open();
|
||||
|
||||
var options = new DbContextOptionsBuilder<TestDatabase>()
|
||||
.UseSqlite(_connection)
|
||||
.Options;
|
||||
|
||||
Database = new TestDatabase(options);
|
||||
Database.Database.EnsureCreated();
|
||||
}
|
||||
|
||||
public TestDatabase NewContext()
|
||||
{
|
||||
var options = new DbContextOptionsBuilder<TestDatabase>()
|
||||
.UseSqlite(_connection)
|
||||
.Options;
|
||||
return new TestDatabase(options);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Database.Dispose();
|
||||
_connection.Dispose();
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
await Database.DisposeAsync();
|
||||
await _connection.DisposeAsync();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
using Musify.Application.Configuration;
|
||||
using Musify.Domain.Entities;
|
||||
using Musify.Domain.ValueObjects;
|
||||
|
||||
namespace Musify.Application.Tests.Infrastructure;
|
||||
|
||||
public static class TestData
|
||||
{
|
||||
public const string Bucket = "musify-test";
|
||||
|
||||
public static ApplicationStorageConfiguration StorageConfig() => new() { Bucket = Bucket };
|
||||
|
||||
public static UploadIntentConfiguration UploadIntentConfig() => new();
|
||||
|
||||
public static TrackConfiguration TrackConfig() => new();
|
||||
|
||||
public static PlayListConfiguration PlayListConfig() => new();
|
||||
|
||||
public static User User(Guid? id = null, string name = "Alice") => new()
|
||||
{
|
||||
Id = id ?? Guid.NewGuid(),
|
||||
Name = name,
|
||||
NormalizedName = name.ToUpperInvariant(),
|
||||
};
|
||||
|
||||
public static UploadIntent UploadIntent(
|
||||
Guid userId,
|
||||
UploadIntentPurpose purpose = UploadIntentPurpose.TrackPicture,
|
||||
UploadIntentStatus status = UploadIntentStatus.Issued,
|
||||
DateTime? expiresAt = null,
|
||||
long? expectedSizeBytes = null,
|
||||
string objectName = "object.webp",
|
||||
string? key = null) => new()
|
||||
{
|
||||
UserId = userId,
|
||||
Bucket = Bucket,
|
||||
Key = key ?? $"temp/{userId}/Tracks/{objectName}",
|
||||
ObjectName = objectName,
|
||||
ContentType = "image/webp",
|
||||
ExpectedSizeBytes = expectedSizeBytes,
|
||||
Purpose = purpose,
|
||||
Status = status,
|
||||
ExpiresAt = expiresAt ?? DateTime.UtcNow.AddMinutes(5),
|
||||
};
|
||||
|
||||
public static Track Track(
|
||||
string title = "Song",
|
||||
ProcessingStatus audioStatus = ProcessingStatus.Completed,
|
||||
LifeCycleStatus lifeCycle = LifeCycleStatus.Active) => new()
|
||||
{
|
||||
Title = title,
|
||||
NormalizedTitle = title.ToUpperInvariant(),
|
||||
OriginalPictureName = "pic.webp",
|
||||
OriginalAudioName = "audio.mp3",
|
||||
AudioTranscodeProcessingStatus = audioStatus,
|
||||
PicturesProcessingStatus = ProcessingStatus.Completed,
|
||||
LifeCycleStatus = lifeCycle,
|
||||
};
|
||||
|
||||
public static PlayList PlayList(
|
||||
Guid userId,
|
||||
string name = "My PlayList",
|
||||
LifeCycleStatus lifeCycle = LifeCycleStatus.Active) => new()
|
||||
{
|
||||
UserId = userId,
|
||||
Name = name,
|
||||
NormalizedName = name.ToUpperInvariant(),
|
||||
Description = "desc",
|
||||
OriginalPictureName = "orig.webp",
|
||||
SmallPictureName = "small.webp",
|
||||
MediumPictureName = "medium.webp",
|
||||
LargePictureName = "large.webp",
|
||||
LifeCycleStatus = lifeCycle,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Storage;
|
||||
using Musify.Domain.Entities;
|
||||
using AppIDatabase = Musify.Application.Contracts.IDatabase;
|
||||
using IDatabaseTransaction = Musify.Application.Contracts.IDatabaseTransaction;
|
||||
|
||||
namespace Musify.Application.Tests.Infrastructure;
|
||||
|
||||
public sealed class TestDatabase(DbContextOptions<TestDatabase> options) : DbContext(options), AppIDatabase
|
||||
{
|
||||
public DbSet<User> Users => Set<User>();
|
||||
|
||||
public DbSet<Track> Tracks => Set<Track>();
|
||||
|
||||
public DbSet<PlayList> PlayLists => Set<PlayList>();
|
||||
|
||||
public DbSet<UserHasTrack> UserHasTracks => Set<UserHasTrack>();
|
||||
|
||||
public DbSet<PlayListHasTrack> PlayListHasTracks => Set<PlayListHasTrack>();
|
||||
|
||||
public DbSet<Upload> Uploads => Set<Upload>();
|
||||
|
||||
public DbSet<UploadIntent> UploadIntents => Set<UploadIntent>();
|
||||
|
||||
public async Task<IDatabaseTransaction> BeginTransactionAsync(
|
||||
System.Data.IsolationLevel isolationLevel, CancellationToken cancellationToken)
|
||||
{
|
||||
var transaction = await Database.BeginTransactionAsync(isolationLevel, cancellationToken);
|
||||
return new TestDatabaseTransaction(transaction);
|
||||
}
|
||||
|
||||
private sealed class TestDatabaseTransaction(IDbContextTransaction inner) : IDatabaseTransaction
|
||||
{
|
||||
public Task CommitAsync(CancellationToken cancellationToken = default) =>
|
||||
inner.CommitAsync(cancellationToken);
|
||||
|
||||
public ValueTask DisposeAsync() => inner.DisposeAsync();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user