Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions Neolution.Extensions.DataSeeding.UnitTests/AbstractSeedTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using Neolution.Extensions.DataSeeding.Abstractions;
using Neolution.Extensions.DataSeeding.UnitTests.Fakes;
using Neolution.Extensions.DataSeeding.UnitTests.Fakes.MultiTenantSeeds;
using Neolution.Extensions.DataSeeding.UnitTests.Fakes.Services;
using Shouldly;
using Xunit;
using Xunit.Abstractions;
Expand Down Expand Up @@ -96,6 +97,15 @@ private IServiceCollection CreateServiceCollection()
{
var services = new ServiceCollection();
services.AddLogging(builder => builder.AddXUnit(this.testOutputHelper));

// Register fake services with different lifetimes to test scoped service injection
services.AddSingleton<IFakeSingletonService, FakeSingletonService>();
services.AddScoped<IFakeScopedService, FakeScopedService>();
services.AddTransient<IFakeTransientService, FakeTransientService>();

// Register the scoped service with dependency to test UserManager-like scenarios
services.AddScoped<IFakeScopedServiceWithDependency, FakeScopedServiceWithDependency>();

return services;
}
}
Expand Down
9 changes: 9 additions & 0 deletions Neolution.Extensions.DataSeeding.UnitTests/BasicTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Neolution.Extensions.DataSeeding.UnitTests.Fakes;
using Neolution.Extensions.DataSeeding.UnitTests.Fakes.Services;
using Shouldly;
using Xunit;
using Xunit.Abstractions;
Expand Down Expand Up @@ -54,6 +55,14 @@ private IServiceCollection CreateServiceCollection()
{
var services = new ServiceCollection();
services.AddLogging(builder => builder.AddXUnit(this.testOutputHelper).SetMinimumLevel(LogLevel.Debug));

// Register fake services with different lifetimes to test scoped service injection
services.AddSingleton<IFakeSingletonService, FakeSingletonService>();
services.AddScoped<IFakeScopedService, FakeScopedService>();
services.AddTransient<IFakeTransientService, FakeTransientService>();

// Register the scoped service with dependency to test UserManager-like scenarios
services.AddScoped<IFakeScopedServiceWithDependency, FakeScopedServiceWithDependency>();
return services;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Neolution.Extensions.DataSeeding.Abstractions;
using Neolution.Extensions.DataSeeding.UnitTests.Fakes.Services;

/// <inheritdoc />
public class ApplicationSettingsSeed : ISeed
Expand All @@ -12,19 +13,48 @@ public class ApplicationSettingsSeed : ISeed
/// </summary>
private readonly ILogger<ApplicationSettingsSeed> logger;

/// <summary>
/// The singleton service
/// </summary>
private readonly IFakeSingletonService singletonService;

/// <summary>
/// The scoped service
/// </summary>
private readonly IFakeScopedService scopedService;

/// <summary>
/// The transient service
/// </summary>
private readonly IFakeTransientService transientService;

/// <summary>
/// Initializes a new instance of the <see cref="ApplicationSettingsSeed"/> class.
/// </summary>
/// <param name="logger">The logger.</param>
public ApplicationSettingsSeed(ILogger<ApplicationSettingsSeed> logger)
/// <param name="singletonService">The singleton service.</param>
/// <param name="scopedService">The scoped service.</param>
/// <param name="transientService">The transient service.</param>
public ApplicationSettingsSeed(
ILogger<ApplicationSettingsSeed> logger,
IFakeSingletonService singletonService,
IFakeScopedService scopedService,
IFakeTransientService transientService)
{
this.logger = logger;
this.singletonService = singletonService;
this.scopedService = scopedService;
this.transientService = transientService;
}

/// <inheritdoc />
public Task SeedAsync()
{
this.logger.LogInformation("Seed() called");
this.logger.LogInformation(
"Seed() called with Singleton: {SingletonId}, Scoped: {ScopedId}, Transient: {TransientId}",
this.singletonService.ServiceId,
this.scopedService.ServiceId,
this.transientService.ServiceId);
return Task.CompletedTask;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
namespace Neolution.Extensions.DataSeeding.UnitTests.Fakes.MultiTenantSeeds
{
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Neolution.Extensions.DataSeeding.Abstractions;
using Neolution.Extensions.DataSeeding.UnitTests.Fakes.Services;

/// <summary>
/// A seed that tests scoped service dependencies similar to UserManager scenario.
/// </summary>
public class ScopedServiceWithDependencySeed : ISeed
{
/// <summary>
/// The logger
/// </summary>
private readonly ILogger<ScopedServiceWithDependencySeed> logger;

/// <summary>
/// The scoped service with dependency
/// </summary>
private readonly IFakeScopedServiceWithDependency scopedServiceWithDependency;

/// <summary>
/// Initializes a new instance of the <see cref="ScopedServiceWithDependencySeed"/> class.
/// </summary>
/// <param name="logger">The logger.</param>
/// <param name="scopedServiceWithDependency">The scoped service with dependency.</param>
public ScopedServiceWithDependencySeed(
ILogger<ScopedServiceWithDependencySeed> logger,
IFakeScopedServiceWithDependency scopedServiceWithDependency)
{
this.logger = logger;
this.scopedServiceWithDependency = scopedServiceWithDependency;
}

/// <inheritdoc />
public async Task SeedAsync()
{
this.logger.LogInformation("Starting scoped service with dependency seed");

// This should trigger ObjectDisposedException if scope is disposed
var result = await this.scopedServiceWithDependency.PerformScopedOperationAsync();

this.logger.LogInformation("Scoped operation result: {Result}", result);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace Neolution.Extensions.DataSeeding.UnitTests.Fakes.Services
{
/// <summary>
/// Fake scoped service implementation.
/// </summary>
public class FakeScopedService : IFakeScopedService
{
/// <summary>
/// Initializes a new instance of the <see cref="FakeScopedService"/> class.
/// </summary>
public FakeScopedService()
{
this.ServiceId = System.Guid.NewGuid().ToString();
}

/// <inheritdoc />
public string ServiceId { get; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
namespace Neolution.Extensions.DataSeeding.UnitTests.Fakes.Services
{
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;

/// <summary>
/// A scoped service that depends on other scoped services, similar to UserManager.
/// </summary>
public class FakeScopedServiceWithDependency : IFakeScopedServiceWithDependency
{
/// <summary>
/// The service provider.
/// </summary>
private readonly IServiceProvider serviceProvider;

/// <summary>
/// Initializes a new instance of the <see cref="FakeScopedServiceWithDependency"/> class.
/// </summary>
/// <param name="serviceProvider">The service provider.</param>
public FakeScopedServiceWithDependency(IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider;
}

/// <summary>
/// Performs an async operation that accesses scoped dependencies.
/// </summary>
/// <returns>A task representing the async operation.</returns>
public async Task<string> PerformScopedOperationAsync()
{
// This simulates UserManager.CreateAsync accessing other scoped services
var scopedService = this.serviceProvider.GetRequiredService<IFakeScopedService>();
await Task.Delay(1); // Simulate async work
return $"Operation completed with {scopedService.ServiceId}";
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace Neolution.Extensions.DataSeeding.UnitTests.Fakes.Services
{
/// <summary>
/// Fake singleton service implementation.
/// </summary>
public class FakeSingletonService : IFakeSingletonService
{
/// <summary>
/// Initializes a new instance of the <see cref="FakeSingletonService"/> class.
/// </summary>
public FakeSingletonService()
{
this.ServiceId = System.Guid.NewGuid().ToString();
}

/// <inheritdoc />
public string ServiceId { get; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace Neolution.Extensions.DataSeeding.UnitTests.Fakes.Services
{
/// <summary>
/// Fake transient service implementation.
/// </summary>
public class FakeTransientService : IFakeTransientService
{
/// <summary>
/// Initializes a new instance of the <see cref="FakeTransientService"/> class.
/// </summary>
public FakeTransientService()
{
this.ServiceId = System.Guid.NewGuid().ToString();
}

/// <inheritdoc />
public string ServiceId { get; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace Neolution.Extensions.DataSeeding.UnitTests.Fakes.Services
{
/// <summary>
/// Fake scoped service interface.
/// </summary>
public interface IFakeScopedService
{
/// <summary>
/// Gets the service identifier.
/// </summary>
string ServiceId { get; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace Neolution.Extensions.DataSeeding.UnitTests.Fakes.Services
{
using System.Threading.Tasks;

/// <summary>
/// Interface for a scoped service that depends on other scoped services.
/// </summary>
public interface IFakeScopedServiceWithDependency
{
/// <summary>
/// Performs an async operation that accesses scoped dependencies.
/// </summary>
/// <returns>A task representing the async operation.</returns>
Task<string> PerformScopedOperationAsync();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace Neolution.Extensions.DataSeeding.UnitTests.Fakes.Services
{
/// <summary>
/// Fake singleton service interface.
/// </summary>
public interface IFakeSingletonService
{
/// <summary>
/// Gets the service identifier.
/// </summary>
string ServiceId { get; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace Neolution.Extensions.DataSeeding.UnitTests.Fakes.Services
{
/// <summary>
/// Fake transient service interface.
/// </summary>
public interface IFakeTransientService
{
/// <summary>
/// Gets the service identifier.
/// </summary>
string ServiceId { get; }
}
}
Loading
Loading