@@ -0,0 +1,46 @@ | |||||
using System; | |||||
using System.Data.SqlClient; | |||||
namespace DotNetCore.CAP.EntityFrameworkCore.Test | |||||
{ | |||||
public static class ConnectionUtil | |||||
{ | |||||
private const string DatabaseVariable = "Cap_SqlServer_DatabaseName"; | |||||
private const string ConnectionStringTemplateVariable = "Cap_SqlServer_ConnectionStringTemplate"; | |||||
private const string MasterDatabaseName = "master"; | |||||
private const string DefaultDatabaseName = @"DotNetCore.CAP.EntityFrameworkCore.Test"; | |||||
private const string DefaultConnectionStringTemplate = @"Server=.\sqlexpress;Database={0};Trusted_Connection=True;"; | |||||
public static string GetDatabaseName() | |||||
{ | |||||
return Environment.GetEnvironmentVariable(DatabaseVariable) ?? DefaultDatabaseName; | |||||
} | |||||
public static string GetMasterConnectionString() | |||||
{ | |||||
return string.Format(GetConnectionStringTemplate(), MasterDatabaseName); | |||||
} | |||||
public static string GetConnectionString() | |||||
{ | |||||
return string.Format(GetConnectionStringTemplate(), GetDatabaseName()); | |||||
} | |||||
private static string GetConnectionStringTemplate() | |||||
{ | |||||
return | |||||
Environment.GetEnvironmentVariable(ConnectionStringTemplateVariable) ?? | |||||
DefaultConnectionStringTemplate; | |||||
} | |||||
public static SqlConnection CreateConnection(string connectionString = null) | |||||
{ | |||||
connectionString = connectionString ?? GetConnectionString(); | |||||
var connection = new SqlConnection(connectionString); | |||||
connection.Open(); | |||||
return connection; | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,61 @@ | |||||
using System.Data; | |||||
using Dapper; | |||||
using Microsoft.EntityFrameworkCore; | |||||
namespace DotNetCore.CAP.EntityFrameworkCore.Test | |||||
{ | |||||
public abstract class DatabaseTestHost : TestHost | |||||
{ | |||||
private static bool _sqlObjectInstalled; | |||||
protected override void PostBuildServices() | |||||
{ | |||||
base.PostBuildServices(); | |||||
InitializeDatabase(); | |||||
} | |||||
public override void Dispose() | |||||
{ | |||||
DeleteAllData(); | |||||
base.Dispose(); | |||||
} | |||||
private void InitializeDatabase() | |||||
{ | |||||
if (!_sqlObjectInstalled) | |||||
{ | |||||
using (CreateScope()) | |||||
{ | |||||
var context = GetService<CapDbContext>(); | |||||
context.Database.EnsureDeleted(); | |||||
context.Database.Migrate(); | |||||
_sqlObjectInstalled = true; | |||||
} | |||||
} | |||||
} | |||||
private void DeleteAllData() | |||||
{ | |||||
using (CreateScope()) | |||||
{ | |||||
var context = GetService<CapDbContext>(); | |||||
var commands = new[] | |||||
{ | |||||
"DISABLE TRIGGER ALL ON ?", | |||||
"ALTER TABLE ? NOCHECK CONSTRAINT ALL", | |||||
"DELETE FROM ?", | |||||
"ALTER TABLE ? CHECK CONSTRAINT ALL", | |||||
"ENABLE TRIGGER ALL ON ?" | |||||
}; | |||||
foreach (var command in commands) | |||||
{ | |||||
context.Database.GetDbConnection().Execute( | |||||
"sp_MSforeachtable", | |||||
new { command1 = command }, | |||||
commandType: CommandType.StoredProcedure); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -7,7 +7,7 @@ namespace DotNetCore.CAP.EntityFrameworkCore.Test | |||||
public static class DbUtil | public static class DbUtil | ||||
{ | { | ||||
public static IServiceCollection ConfigureDbServices(string connectionString, IServiceCollection services = null) { | public static IServiceCollection ConfigureDbServices(string connectionString, IServiceCollection services = null) { | ||||
return ConfigureDbServices<ConsistencyDbContext>(connectionString, services); | |||||
return ConfigureDbServices<CapDbContext>(connectionString, services); | |||||
} | } | ||||
public static IServiceCollection ConfigureDbServices<TContext>(string connectionString, IServiceCollection services = null) where TContext : DbContext { | public static IServiceCollection ConfigureDbServices<TContext>(string connectionString, IServiceCollection services = null) where TContext : DbContext { | ||||
@@ -1,55 +1,57 @@ | |||||
//using System.Threading.Tasks; | |||||
//using DotNetCore.CAP.Infrastructure; | |||||
//using DotNetCore.CAP.Store; | |||||
//using Microsoft.AspNetCore.Builder.Internal; | |||||
//using Microsoft.AspNetCore.Testing.xunit; | |||||
//using Microsoft.EntityFrameworkCore; | |||||
//using Microsoft.Extensions.DependencyInjection; | |||||
//using Xunit; | |||||
//namespace DotNetCore.CAP.EntityFrameworkCore.Test | |||||
//{ | |||||
// public class DefaultPocoTest : IClassFixture<ScratchDatabaseFixture> | |||||
// { | |||||
// private readonly ApplicationBuilder _builder; | |||||
// public DefaultPocoTest(ScratchDatabaseFixture fixture) { | |||||
// var services = new ServiceCollection(); | |||||
// services | |||||
// .AddDbContext<ConsistencyDbContext>(o => o.UseSqlServer(fixture.ConnectionString)) | |||||
// .AddConsistency() | |||||
// .AddEntityFrameworkStores<ConsistencyDbContext>(); | |||||
// services.AddLogging(); | |||||
// var provider = services.BuildServiceProvider(); | |||||
// _builder = new ApplicationBuilder(provider); | |||||
// using (var scoped = provider.GetRequiredService<IServiceScopeFactory>().CreateScope()) | |||||
// using (var db = scoped.ServiceProvider.GetRequiredService<ConsistencyDbContext>()) { | |||||
// db.Database.EnsureCreated(); | |||||
// } | |||||
// } | |||||
// [ConditionalFact] | |||||
// [FrameworkSkipCondition(RuntimeFrameworks.Mono)] | |||||
// [OSSkipCondition(OperatingSystems.Linux)] | |||||
// [OSSkipCondition(OperatingSystems.MacOSX)] | |||||
// public async Task EnsureStartupUsageWorks() { | |||||
// var messageStore = _builder.ApplicationServices.GetRequiredService<IConsistencyMessageStore>(); | |||||
// var messageManager = _builder.ApplicationServices.GetRequiredService<IConsistencyMessageStore >(); | |||||
// Assert.NotNull(messageStore); | |||||
// Assert.NotNull(messageManager); | |||||
// var user = new ConsistencyMessage(); | |||||
// var operateResult = await messageManager.CreateAsync(user); | |||||
// Assert.True(operateResult.Succeeded); | |||||
// operateResult = await messageManager.DeleteAsync(user); | |||||
// Assert.True(operateResult.Succeeded); | |||||
// } | |||||
// } | |||||
//} | |||||
using System.Threading.Tasks; | |||||
using DotNetCore.CAP.Infrastructure; | |||||
using Microsoft.AspNetCore.Builder.Internal; | |||||
using Microsoft.AspNetCore.Testing.xunit; | |||||
using Microsoft.EntityFrameworkCore; | |||||
using Microsoft.Extensions.DependencyInjection; | |||||
using Xunit; | |||||
namespace DotNetCore.CAP.EntityFrameworkCore.Test | |||||
{ | |||||
public class DefaultPocoTest : IClassFixture<ScratchDatabaseFixture> | |||||
{ | |||||
private readonly ApplicationBuilder _builder; | |||||
public DefaultPocoTest(ScratchDatabaseFixture fixture) | |||||
{ | |||||
var services = new ServiceCollection(); | |||||
services | |||||
.AddDbContext<CapDbContext>(o => o.UseSqlServer(fixture.ConnectionString)) | |||||
.AddConsistency() | |||||
.AddEntityFrameworkStores<CapDbContext>(); | |||||
services.AddLogging(); | |||||
var provider = services.BuildServiceProvider(); | |||||
_builder = new ApplicationBuilder(provider); | |||||
using (var scoped = provider.GetRequiredService<IServiceScopeFactory>().CreateScope()) | |||||
using (var db = scoped.ServiceProvider.GetRequiredService<CapDbContext>()) | |||||
{ | |||||
db.Database.EnsureCreated(); | |||||
} | |||||
} | |||||
[ConditionalFact] | |||||
[FrameworkSkipCondition(RuntimeFrameworks.Mono)] | |||||
[OSSkipCondition(OperatingSystems.Linux)] | |||||
[OSSkipCondition(OperatingSystems.MacOSX)] | |||||
public async Task EnsureStartupUsageWorks() | |||||
{ | |||||
var messageStore = _builder.ApplicationServices.GetRequiredService<ICapMessageStore>(); | |||||
var messageManager = _builder.ApplicationServices.GetRequiredService<ICapMessageStore>(); | |||||
Assert.NotNull(messageStore); | |||||
Assert.NotNull(messageManager); | |||||
var message = new CapSentMessage(); | |||||
var operateResult = await messageManager.StoreSentMessageAsync(message); | |||||
Assert.True(operateResult.Succeeded); | |||||
operateResult = await messageManager.RemoveSentMessageAsync(message); | |||||
Assert.True(operateResult.Succeeded); | |||||
} | |||||
} | |||||
} |
@@ -23,6 +23,7 @@ | |||||
</ItemGroup> | </ItemGroup> | ||||
<ItemGroup> | <ItemGroup> | ||||
<PackageReference Include="Dapper" Version="1.50.2" /> | |||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" /> | <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" /> | ||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" /> | <PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" /> | ||||
<PackageReference Include="xunit" Version="2.2.0" /> | <PackageReference Include="xunit" Version="2.2.0" /> | ||||
@@ -0,0 +1,12 @@ | |||||
using Xunit; | |||||
namespace DotNetCore.CAP.EntityFrameworkCore.Test | |||||
{ | |||||
public class EnsuranceTest : DatabaseTestHost | |||||
{ | |||||
[Fact] | |||||
public void Ensure() | |||||
{ | |||||
} | |||||
} | |||||
} |
@@ -1,103 +1,118 @@ | |||||
//using System; | |||||
//using System.Linq; | |||||
//using System.Threading.Tasks; | |||||
//using DotNetCore.CAP.Infrastructure; | |||||
//using DotNetCore.CAP.Store; | |||||
//using DotNetCore.CAP.Test; | |||||
//using Microsoft.AspNetCore.Testing; | |||||
//using Microsoft.AspNetCore.Testing.xunit; | |||||
//using Microsoft.EntityFrameworkCore; | |||||
//using Microsoft.Extensions.DependencyInjection; | |||||
//using Xunit; | |||||
using System; | |||||
using System.Linq; | |||||
using System.Threading.Tasks; | |||||
using DotNetCore.CAP.Infrastructure; | |||||
using DotNetCore.CAP.Test; | |||||
using Microsoft.AspNetCore.Testing; | |||||
using Microsoft.AspNetCore.Testing.xunit; | |||||
using Microsoft.EntityFrameworkCore; | |||||
using Microsoft.Extensions.DependencyInjection; | |||||
using Xunit; | |||||
//namespace DotNetCore.CAP.EntityFrameworkCore.Test | |||||
//{ | |||||
// public class MessageStoreTest : MessageManagerTestBase<ConsistencyMessage>, IClassFixture<ScratchDatabaseFixture> | |||||
// { | |||||
// private readonly ScratchDatabaseFixture _fixture; | |||||
namespace DotNetCore.CAP.EntityFrameworkCore.Test | |||||
{ | |||||
public class MessageStoreTest : MessageManagerTestBase, IClassFixture<ScratchDatabaseFixture> | |||||
{ | |||||
private readonly ScratchDatabaseFixture _fixture; | |||||
// public MessageStoreTest(ScratchDatabaseFixture fixture) { | |||||
// _fixture = fixture; | |||||
// } | |||||
public MessageStoreTest(ScratchDatabaseFixture fixture) | |||||
{ | |||||
_fixture = fixture; | |||||
} | |||||
// protected override bool ShouldSkipDbTests() { | |||||
// return TestPlatformHelper.IsMono || !TestPlatformHelper.IsWindows; | |||||
// } | |||||
protected override bool ShouldSkipDbTests() | |||||
{ | |||||
return TestPlatformHelper.IsMono || !TestPlatformHelper.IsWindows; | |||||
} | |||||
// public class ApplicationDbContext : ConsistencyDbContext | |||||
// { | |||||
// public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { | |||||
// } | |||||
// } | |||||
public class ApplicationDbContext : CapDbContext | |||||
{ | |||||
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) | |||||
{ | |||||
} | |||||
} | |||||
// [ConditionalFact] | |||||
// [FrameworkSkipCondition(RuntimeFrameworks.Mono)] | |||||
// [OSSkipCondition(OperatingSystems.Linux)] | |||||
// [OSSkipCondition(OperatingSystems.MacOSX)] | |||||
// public void CanCreateMessageUsingEF() { | |||||
// using (var db = CreateContext()) { | |||||
// var guid = Guid.NewGuid().ToString(); | |||||
// db.Messages.Add(new ConsistencyMessage { | |||||
// Id = guid, | |||||
// Payload = "this is message body", | |||||
// Status = MessageStatus.WaitForSend, | |||||
// SendTime = DateTime.Now, | |||||
// UpdateTime = DateTime.Now | |||||
// }); | |||||
[ConditionalFact] | |||||
[FrameworkSkipCondition(RuntimeFrameworks.Mono)] | |||||
[OSSkipCondition(OperatingSystems.Linux)] | |||||
[OSSkipCondition(OperatingSystems.MacOSX)] | |||||
public void CanCreateSentMessageUsingEF() | |||||
{ | |||||
using (var db = CreateContext()) | |||||
{ | |||||
var guid = Guid.NewGuid().ToString(); | |||||
db.CapSentMessages.Add(new CapSentMessage | |||||
{ | |||||
Id = guid, | |||||
Content = "this is message body", | |||||
StateName = StateName.Enqueued | |||||
}); | |||||
// db.SaveChanges(); | |||||
// Assert.True(db.Messages.Any(u => u.Id == guid)); | |||||
// Assert.NotNull(db.Messages.FirstOrDefault(u => u.Status == MessageStatus.WaitForSend)); | |||||
// } | |||||
// } | |||||
db.SaveChanges(); | |||||
Assert.True(db.CapSentMessages.Any(u => u.Id == guid)); | |||||
Assert.NotNull(db.CapSentMessages.FirstOrDefault(u => u.StateName == StateName.Enqueued)); | |||||
} | |||||
} | |||||
// [ConditionalFact] | |||||
// [FrameworkSkipCondition(RuntimeFrameworks.Mono)] | |||||
// [OSSkipCondition(OperatingSystems.Linux)] | |||||
// [OSSkipCondition(OperatingSystems.MacOSX)] | |||||
// public async Task CanCreateUsingManager() { | |||||
// var manager = CreateManager(); | |||||
// var guid = Guid.NewGuid().ToString(); | |||||
// var message = new ConsistencyMessage { | |||||
// Id = guid, | |||||
// Payload = "this is message body", | |||||
// Status = MessageStatus.WaitForSend, | |||||
// SendTime = DateTime.Now, | |||||
// UpdateTime = DateTime.Now | |||||
// }; | |||||
[ConditionalFact] | |||||
[FrameworkSkipCondition(RuntimeFrameworks.Mono)] | |||||
[OSSkipCondition(OperatingSystems.Linux)] | |||||
[OSSkipCondition(OperatingSystems.MacOSX)] | |||||
public async Task CanCreateUsingManager() | |||||
{ | |||||
var manager = CreateManager(); | |||||
var guid = Guid.NewGuid().ToString(); | |||||
var message = new CapSentMessage | |||||
{ | |||||
Id = guid, | |||||
Content = "this is message body", | |||||
StateName = StateName.Enqueued, | |||||
}; | |||||
// var result = await manager.CreateAsync(message); | |||||
// Assert.NotNull(result); | |||||
// Assert.True(result.Succeeded); | |||||
var result = await manager.StoreSentMessageAsync(message); | |||||
Assert.NotNull(result); | |||||
Assert.True(result.Succeeded); | |||||
// result = await manager.DeleteAsync(message); | |||||
// Assert.NotNull(result); | |||||
// Assert.True(result.Succeeded); | |||||
// } | |||||
result = await manager.RemoveSentMessageAsync(message); | |||||
Assert.NotNull(result); | |||||
Assert.True(result.Succeeded); | |||||
} | |||||
// public ConsistencyDbContext CreateContext(bool delete = false) { | |||||
// var db = DbUtil.Create<ConsistencyDbContext>(_fixture.ConnectionString); | |||||
// if (delete) { | |||||
// db.Database.EnsureDeleted(); | |||||
// } | |||||
// db.Database.EnsureCreated(); | |||||
// return db; | |||||
// } | |||||
public CapDbContext CreateContext(bool delete = false) | |||||
{ | |||||
var db = DbUtil.Create<CapDbContext>(_fixture.ConnectionString); | |||||
if (delete) | |||||
{ | |||||
db.Database.EnsureDeleted(); | |||||
} | |||||
db.Database.EnsureCreated(); | |||||
return db; | |||||
} | |||||
// protected override object CreateTestContext() { | |||||
// return CreateContext(); | |||||
// } | |||||
protected override object CreateTestContext() | |||||
{ | |||||
return CreateContext(); | |||||
} | |||||
// protected override ConsistencyMessage CreateTestMessage(string payload = "") { | |||||
// return new ConsistencyMessage { | |||||
// Payload = payload | |||||
// }; | |||||
// } | |||||
protected override void AddMessageStore(IServiceCollection services, object context = null) | |||||
{ | |||||
services.AddSingleton<ICapMessageStore>(new CapMessageStore<CapDbContext>((CapDbContext)context)); | |||||
} | |||||
// protected override void AddMessageStore(IServiceCollection services, object context = null) { | |||||
// services.AddSingleton<IConsistencyMessageStore>(new ConsistencyMessageStore<ConsistencyDbContext>((ConsistencyDbContext)context)); | |||||
// } | |||||
// } | |||||
protected override CapSentMessage CreateTestSentMessage(string content = "") | |||||
{ | |||||
return new CapSentMessage | |||||
{ | |||||
Content = content | |||||
}; | |||||
} | |||||
// public class ApplicationMessage : ConsistencyMessage { } | |||||
//} | |||||
protected override CapReceivedMessage CreateTestReceivedMessage(string content = "") | |||||
{ | |||||
return new CapReceivedMessage() | |||||
{ | |||||
Content = content | |||||
}; | |||||
} | |||||
} | |||||
} |
@@ -1,62 +0,0 @@ | |||||
//using System; | |||||
//using DotNetCore.CAP.Infrastructure; | |||||
//using DotNetCore.CAP.Store; | |||||
//using DotNetCore.CAP.Test; | |||||
//using Microsoft.AspNetCore.Testing; | |||||
//using Microsoft.Extensions.DependencyInjection; | |||||
//using Xunit; | |||||
//namespace DotNetCore.CAP.EntityFrameworkCore.Test | |||||
//{ | |||||
// public class MessageStoreWithGenericsTest : MessageManagerTestBase<MessageWithGenerics, string>, IClassFixture<ScratchDatabaseFixture> | |||||
// { | |||||
// private readonly ScratchDatabaseFixture _fixture; | |||||
// public MessageStoreWithGenericsTest(ScratchDatabaseFixture fixture) { | |||||
// _fixture = fixture; | |||||
// } | |||||
// protected override void AddMessageStore(IServiceCollection services, object context = null) { | |||||
// services.AddSingleton<IConsistencyMessageStore>(new MessageStoreWithGenerics((ContextWithGenerics)context)); | |||||
// } | |||||
// protected override object CreateTestContext() { | |||||
// return CreateContext(); | |||||
// } | |||||
// public ContextWithGenerics CreateContext() { | |||||
// var db = DbUtil.Create<ContextWithGenerics>(_fixture.ConnectionString); | |||||
// db.Database.EnsureCreated(); | |||||
// return db; | |||||
// } | |||||
// protected override MessageWithGenerics CreateTestMessage(string payload = "") { | |||||
// return new MessageWithGenerics() { | |||||
// Payload = payload, | |||||
// SendTime = DateTime.Now, | |||||
// Status = MessageStatus.WaitForSend, | |||||
// UpdateTime = DateTime.Now | |||||
// }; | |||||
// } | |||||
// protected override bool ShouldSkipDbTests() { | |||||
// return TestPlatformHelper.IsMono || !TestPlatformHelper.IsWindows; | |||||
// } | |||||
// } | |||||
// public class MessageWithGenerics : ConsistencyMessage | |||||
// { | |||||
// } | |||||
// public class MessageStoreWithGenerics : ConsistencyMessageStore<ContextWithGenerics> | |||||
// { | |||||
// public MessageStoreWithGenerics(ContextWithGenerics context) : base(context) { | |||||
// } | |||||
// } | |||||
// public class ContextWithGenerics : ConsistencyDbContext | |||||
// { | |||||
// public ContextWithGenerics() { | |||||
// } | |||||
// } | |||||
//} |
@@ -0,0 +1,97 @@ | |||||
using System; | |||||
using Microsoft.EntityFrameworkCore; | |||||
using Microsoft.Extensions.DependencyInjection; | |||||
namespace DotNetCore.CAP.EntityFrameworkCore.Test | |||||
{ | |||||
public abstract class TestHost : IDisposable | |||||
{ | |||||
protected IServiceCollection _services; | |||||
private IServiceProvider _provider; | |||||
private IServiceProvider _scopedProvider; | |||||
public TestHost() | |||||
{ | |||||
CreateServiceCollection(); | |||||
PreBuildServices(); | |||||
BuildServices(); | |||||
PostBuildServices(); | |||||
} | |||||
protected IServiceProvider Provider => _scopedProvider ?? _provider; | |||||
private void CreateServiceCollection() | |||||
{ | |||||
var services = new ServiceCollection(); | |||||
services.AddOptions(); | |||||
services.AddLogging(); | |||||
var connectionString = ConnectionUtil.GetConnectionString(); | |||||
//services.AddSingleton(new SqlServerOptions { ConnectionString = connectionString }); | |||||
services.AddDbContext<CapDbContext>(options => options.UseSqlServer(connectionString)); | |||||
_services = services; | |||||
} | |||||
protected virtual void PreBuildServices() | |||||
{ | |||||
} | |||||
private void BuildServices() | |||||
{ | |||||
_provider = _services.BuildServiceProvider(); | |||||
} | |||||
protected virtual void PostBuildServices() | |||||
{ | |||||
} | |||||
public IDisposable CreateScope() | |||||
{ | |||||
var scope = CreateScope(_provider); | |||||
var loc = scope.ServiceProvider; | |||||
_scopedProvider = loc; | |||||
return new DelegateDisposable(() => | |||||
{ | |||||
if (_scopedProvider == loc) | |||||
{ | |||||
_scopedProvider = null; | |||||
} | |||||
scope.Dispose(); | |||||
}); | |||||
} | |||||
public IServiceScope CreateScope(IServiceProvider provider) | |||||
{ | |||||
var scope = provider.GetService<IServiceScopeFactory>().CreateScope(); | |||||
return scope; | |||||
} | |||||
public T GetService<T>() => Provider.GetService<T>(); | |||||
public T Ensure<T>(ref T service) | |||||
where T : class | |||||
=> service ?? (service = GetService<T>()); | |||||
public virtual void Dispose() | |||||
{ | |||||
(_provider as IDisposable)?.Dispose(); | |||||
} | |||||
private class DelegateDisposable : IDisposable | |||||
{ | |||||
private Action _dispose; | |||||
public DelegateDisposable(Action dispose) | |||||
{ | |||||
_dispose = dispose; | |||||
} | |||||
public void Dispose() | |||||
{ | |||||
_dispose(); | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -1,7 +1,7 @@ | |||||
{ | { | ||||
"Test": { | "Test": { | ||||
"SqlServer": { | "SqlServer": { | ||||
"DefaultConnectionString": "Server=(localdb)\\MSSqlLocaldb;Integrated Security=true;MultipleActiveResultSets=true;Connect Timeout=30" | |||||
"DefaultConnectionString": "Server=192.168.2.206;Initial Catalog=Test;User Id=cmswuliu;Password=h7xY81agBn*Veiu3;MultipleActiveResultSets=True" | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -32,8 +32,4 @@ | |||||
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" /> | <Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" /> | ||||
</ItemGroup> | </ItemGroup> | ||||
<ItemGroup> | |||||
<Folder Include="Job\" /> | |||||
</ItemGroup> | |||||
</Project> | </Project> |
@@ -0,0 +1,56 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Text; | |||||
using DotNetCore.CAP.Job; | |||||
using Xunit; | |||||
namespace DotNetCore.CAP.Test.Job | |||||
{ | |||||
public class ComputedJobTest | |||||
{ | |||||
[Fact] | |||||
public void UpdateNext_LastRunNever_SchedulesNow() | |||||
{ | |||||
// Arrange | |||||
var now = new DateTime(2000, 1, 1, 8, 0, 0); | |||||
var cronJob = new CronJob(Cron.Daily()); | |||||
var computed = new ComputedCronJob(cronJob); | |||||
// Act | |||||
computed.UpdateNext(now); | |||||
// Assert | |||||
Assert.Equal(computed.Next, now); | |||||
} | |||||
[Fact] | |||||
public void UpdateNext_LastRun_BeforePrev_SchedulesNow() | |||||
{ | |||||
// Arrange | |||||
var now = new DateTime(2000, 1, 1, 8, 0, 0); | |||||
var cronJob = new CronJob(Cron.Daily(), now.Subtract(TimeSpan.FromDays(2))); | |||||
var computed = new ComputedCronJob(cronJob); | |||||
// Act | |||||
computed.UpdateNext(now); | |||||
// Assert | |||||
Assert.Equal(computed.Next, now); | |||||
} | |||||
[Fact] | |||||
public void UpdateNext_LastRun_AfterPrev_SchedulesNormal() | |||||
{ | |||||
// Arrange | |||||
var now = new DateTime(2000, 1, 1, 8, 0, 0); | |||||
var cronJob = new CronJob(Cron.Daily(), now.Subtract(TimeSpan.FromSeconds(5))); | |||||
var computed = new ComputedCronJob(cronJob); | |||||
// Act | |||||
computed.UpdateNext(now); | |||||
// Assert | |||||
Assert.True(computed.Next > now); | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,185 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Text; | |||||
using System.Threading; | |||||
using System.Threading.Tasks; | |||||
using DotNetCore.CAP.Infrastructure; | |||||
using DotNetCore.CAP.Job; | |||||
using Microsoft.Extensions.DependencyInjection; | |||||
using Moq; | |||||
using Xunit; | |||||
namespace DotNetCore.CAP.Test.Job | |||||
{ | |||||
public class JobProcessingServerTest | |||||
{ | |||||
private CancellationTokenSource _cancellationTokenSource; | |||||
private ProcessingContext _context; | |||||
private CapOptions _options; | |||||
private IServiceProvider _provider; | |||||
private Mock<ICapMessageStore> _mockStorage; | |||||
public JobProcessingServerTest() | |||||
{ | |||||
_options = new CapOptions() | |||||
{ | |||||
PollingDelay = 0 | |||||
}; | |||||
_mockStorage = new Mock<ICapMessageStore>(); | |||||
_cancellationTokenSource = new CancellationTokenSource(); | |||||
var services = new ServiceCollection(); | |||||
services.AddTransient<JobProcessingServer>(); | |||||
services.AddTransient<DefaultCronJobRegistry>(); | |||||
services.AddLogging(); | |||||
services.AddSingleton(_options); | |||||
services.AddSingleton(_mockStorage.Object); | |||||
_provider = services.BuildServiceProvider(); | |||||
_context = new ProcessingContext(_provider, null, _cancellationTokenSource.Token); | |||||
} | |||||
//[Fact] | |||||
//public async Task ProcessAsync_CancellationTokenCancelled_ThrowsImmediately() | |||||
//{ | |||||
// // Arrange | |||||
// _cancellationTokenSource.Cancel(); | |||||
// var fixture = Create(); | |||||
// // Act | |||||
// await Assert.ThrowsAsync<OperationCanceledException>(() => fixture.s(_context)); | |||||
//} | |||||
//[Fact] | |||||
//public async Task ProcessAsync() | |||||
//{ | |||||
// // Arrange | |||||
// var job = new CronJob( | |||||
// InvocationData.Serialize( | |||||
// MethodInvocation.FromExpression(() => Method())).Serialize()); | |||||
// var mockFetchedJob = Mock.Get(Mock.Of<IFetchedJob>(fj => fj.JobId == 42)); | |||||
// _mockStorageConnection | |||||
// .Setup(m => m.FetchNextJobAsync()) | |||||
// .ReturnsAsync(mockFetchedJob.Object).Verifiable(); | |||||
// _mockStorageConnection | |||||
// .Setup(m => m.GetJobAsync(42)) | |||||
// .ReturnsAsync(job).Verifiable(); | |||||
// var fixture = Create(); | |||||
// // Act | |||||
// fixture.Start(); | |||||
// // Assert | |||||
// _mockStorageConnection.VerifyAll(); | |||||
// _mockStateChanger.Verify(m => m.ChangeState(job, It.IsAny<SucceededState>(), It.IsAny<IStorageTransaction>())); | |||||
// mockFetchedJob.Verify(m => m.Requeue(), Times.Never); | |||||
// mockFetchedJob.Verify(m => m.RemoveFromQueue()); | |||||
//} | |||||
//[Fact] | |||||
//public async Task ProcessAsync_Exception() | |||||
//{ | |||||
// // Arrange | |||||
// var job = new Job( | |||||
// InvocationData.Serialize( | |||||
// MethodInvocation.FromExpression(() => Throw())).Serialize()); | |||||
// var mockFetchedJob = Mock.Get(Mock.Of<IFetchedJob>(fj => fj.JobId == 42)); | |||||
// _mockStorageConnection | |||||
// .Setup(m => m.FetchNextJobAsync()) | |||||
// .ReturnsAsync(mockFetchedJob.Object); | |||||
// _mockStorageConnection | |||||
// .Setup(m => m.GetJobAsync(42)) | |||||
// .ReturnsAsync(job); | |||||
// _mockStateChanger.Setup(m => m.ChangeState(job, It.IsAny<IState>(), It.IsAny<IStorageTransaction>())) | |||||
// .Throws<Exception>(); | |||||
// var fixture = Create(); | |||||
// // Act | |||||
// await fixture.ProcessAsync(_context); | |||||
// // Assert | |||||
// job.Retries.Should().Be(0); | |||||
// mockFetchedJob.Verify(m => m.Requeue()); | |||||
//} | |||||
//[Fact] | |||||
//public async Task ProcessAsync_JobThrows() | |||||
//{ | |||||
// // Arrange | |||||
// var job = new Job( | |||||
// InvocationData.Serialize( | |||||
// MethodInvocation.FromExpression(() => Throw())).Serialize()); | |||||
// var mockFetchedJob = Mock.Get(Mock.Of<IFetchedJob>(fj => fj.JobId == 42)); | |||||
// _mockStorageConnection | |||||
// .Setup(m => m.FetchNextJobAsync()) | |||||
// .ReturnsAsync(mockFetchedJob.Object).Verifiable(); | |||||
// _mockStorageConnection | |||||
// .Setup(m => m.GetJobAsync(42)) | |||||
// .ReturnsAsync(job).Verifiable(); | |||||
// var fixture = Create(); | |||||
// // Act | |||||
// await fixture.ProcessAsync(_context); | |||||
// // Assert | |||||
// job.Retries.Should().Be(1); | |||||
// _mockStorageTransaction.Verify(m => m.UpdateJob(job)); | |||||
// _mockStorageConnection.VerifyAll(); | |||||
// _mockStateChanger.Verify(m => m.ChangeState(job, It.IsAny<ScheduledState>(), It.IsAny<IStorageTransaction>())); | |||||
// mockFetchedJob.Verify(m => m.RemoveFromQueue()); | |||||
//} | |||||
//[Fact] | |||||
//public async Task ProcessAsync_JobThrows_WithNoRetry() | |||||
//{ | |||||
// // Arrange | |||||
// var job = new Job( | |||||
// InvocationData.Serialize( | |||||
// MethodInvocation.FromExpression<NoRetryJob>(j => j.Throw())).Serialize()); | |||||
// var mockFetchedJob = Mock.Get(Mock.Of<IFetchedJob>(fj => fj.JobId == 42)); | |||||
// _mockStorageConnection | |||||
// .Setup(m => m.FetchNextJobAsync()) | |||||
// .ReturnsAsync(mockFetchedJob.Object); | |||||
// _mockStorageConnection | |||||
// .Setup(m => m.GetJobAsync(42)) | |||||
// .ReturnsAsync(job); | |||||
// var fixture = Create(); | |||||
// // Act | |||||
// await fixture.ProcessAsync(_context); | |||||
// // Assert | |||||
// _mockStateChanger.Verify(m => m.ChangeState(job, It.IsAny<FailedState>(), It.IsAny<IStorageTransaction>())); | |||||
//} | |||||
private JobProcessingServer Create() | |||||
=> _provider.GetService<JobProcessingServer>(); | |||||
//public static void Method() { } | |||||
//public static void Throw() { throw new Exception(); } | |||||
//private class NoRetryJob : IRetryable | |||||
//{ | |||||
// public RetryBehavior RetryBehavior => new RetryBehavior(false); | |||||
// public void Throw() { throw new Exception(); } | |||||
//} | |||||
} | |||||
} |
@@ -1,94 +1,113 @@ | |||||
//using System; | |||||
//using System.Collections.Generic; | |||||
//using System.Linq; | |||||
//using System.Linq.Expressions; | |||||
//using System.Security.Claims; | |||||
//using System.Threading.Tasks; | |||||
//using DotNetCore.CAP.Infrastructure; | |||||
//using DotNetCore.CAP.Store; | |||||
//using Microsoft.AspNetCore.Builder; | |||||
//using Microsoft.AspNetCore.Http; | |||||
//using Microsoft.Extensions.DependencyInjection; | |||||
//using Microsoft.Extensions.Logging; | |||||
//using Xunit; | |||||
//namespace DotNetCore.CAP.Test | |||||
//{ | |||||
// public abstract class MessageManagerTestBase<TMessage> : MessageManagerTestBase<TMessage, string> | |||||
// where TMessage : ConsistencyMessage | |||||
// { | |||||
// } | |||||
// public abstract class MessageManagerTestBase<TMessage, TKey> | |||||
// where TMessage : ConsistencyMessage | |||||
// where TKey : IEquatable<TKey> | |||||
// { | |||||
// private const string NullValue = "(null)"; | |||||
// protected virtual bool ShouldSkipDbTests() { | |||||
// return false; | |||||
// } | |||||
// protected virtual void SetupMessageServices(IServiceCollection services, object context = null) { | |||||
// services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); | |||||
// services.AddConsistency(); | |||||
// AddMessageStore(services, context); | |||||
// services.AddSingleton<ILogger<IConsistencyMessageStore >>(new TestLogger<IConsistencyMessageStore >()); | |||||
// } | |||||
// protected virtual IConsistencyMessageStore CreateManager(object context = null, IServiceCollection services = null, Action<IServiceCollection> configureServices = null) { | |||||
// if (services == null) { | |||||
// services = new ServiceCollection(); | |||||
// } | |||||
// if (context == null) { | |||||
// context = CreateTestContext(); | |||||
// } | |||||
// SetupMessageServices(services, context); | |||||
// configureServices?.Invoke(services); | |||||
// return services.BuildServiceProvider().GetService<IConsistencyMessageStore >(); | |||||
// } | |||||
// protected abstract object CreateTestContext(); | |||||
// protected abstract TMessage CreateTestMessage(string payload = ""); | |||||
// protected abstract void AddMessageStore(IServiceCollection services, object context = null); | |||||
// [Fact] | |||||
// public async Task CanDeleteMessage() { | |||||
// if (ShouldSkipDbTests()) { | |||||
// return; | |||||
// } | |||||
// var manager = CreateManager(); | |||||
// var message = CreateTestMessage(); | |||||
// var operateResult = await manager.CreateAsync(message); | |||||
// Assert.NotNull(operateResult); | |||||
// Assert.True(operateResult.Succeeded); | |||||
// var messageId = await manager.GeConsistencyMessageIdAsync(message); | |||||
// operateResult = await manager.DeleteAsync(message); | |||||
// Assert.Null(await manager.FindByIdAsync(messageId)); | |||||
// } | |||||
// [Fact] | |||||
// public async Task CanFindById() { | |||||
// if (ShouldSkipDbTests()) { | |||||
// return; | |||||
// } | |||||
// var manager = CreateManager(); | |||||
// var message = CreateTestMessage(); | |||||
// var operateResult = await manager.CreateAsync(message); | |||||
// Assert.NotNull(operateResult); | |||||
// Assert.True(operateResult.Succeeded); | |||||
// var messageId = await manager.GeConsistencyMessageIdAsync(message); | |||||
// Assert.NotNull(await manager.FindByIdAsync(messageId)); | |||||
// } | |||||
// } | |||||
//} | |||||
using System; | |||||
using System.Threading.Tasks; | |||||
using DotNetCore.CAP.Infrastructure; | |||||
using Microsoft.AspNetCore.Http; | |||||
using Microsoft.Extensions.DependencyInjection; | |||||
using Microsoft.Extensions.Logging; | |||||
using Xunit; | |||||
namespace DotNetCore.CAP.Test | |||||
{ | |||||
public abstract class MessageManagerTestBase | |||||
{ | |||||
private const string NullValue = "(null)"; | |||||
protected virtual bool ShouldSkipDbTests() | |||||
{ | |||||
return false; | |||||
} | |||||
protected virtual void SetupMessageServices(IServiceCollection services, object context = null) | |||||
{ | |||||
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); | |||||
services.AddConsistency(); | |||||
AddMessageStore(services, context); | |||||
services.AddSingleton<ILogger<ICapMessageStore>>(new TestLogger<ICapMessageStore>()); | |||||
} | |||||
protected virtual ICapMessageStore CreateManager(object context = null, IServiceCollection services = null, Action<IServiceCollection> configureServices = null) | |||||
{ | |||||
if (services == null) | |||||
{ | |||||
services = new ServiceCollection(); | |||||
} | |||||
if (context == null) | |||||
{ | |||||
context = CreateTestContext(); | |||||
} | |||||
SetupMessageServices(services, context); | |||||
configureServices?.Invoke(services); | |||||
return services.BuildServiceProvider().GetService<ICapMessageStore>(); | |||||
} | |||||
protected abstract object CreateTestContext(); | |||||
protected abstract CapSentMessage CreateTestSentMessage(string content = ""); | |||||
protected abstract CapReceivedMessage CreateTestReceivedMessage(string content = ""); | |||||
protected abstract void AddMessageStore(IServiceCollection services, object context = null); | |||||
[Fact] | |||||
public async Task CanDeleteSentMessage() | |||||
{ | |||||
if (ShouldSkipDbTests()) | |||||
{ | |||||
return; | |||||
} | |||||
var manager = CreateManager(); | |||||
var message = CreateTestSentMessage(); | |||||
var operateResult = await manager.StoreSentMessageAsync(message); | |||||
Assert.NotNull(operateResult); | |||||
Assert.True(operateResult.Succeeded); | |||||
operateResult = await manager.RemoveSentMessageAsync(message); | |||||
Assert.NotNull(operateResult); | |||||
Assert.True(operateResult.Succeeded); | |||||
} | |||||
[Fact] | |||||
public async Task CanUpdateReceivedMessage() | |||||
{ | |||||
if (ShouldSkipDbTests()) | |||||
{ | |||||
return; | |||||
} | |||||
var manager = CreateManager(); | |||||
var message = CreateTestReceivedMessage(); | |||||
var operateResult = await manager.StoreReceivedMessageAsync(message); | |||||
Assert.NotNull(operateResult); | |||||
Assert.True(operateResult.Succeeded); | |||||
message.StateName = StateName.Processing; | |||||
operateResult = await manager.UpdateReceivedMessageAsync(message); | |||||
Assert.NotNull(operateResult); | |||||
Assert.True(operateResult.Succeeded); | |||||
} | |||||
[Fact] | |||||
public async Task CanGetNextSendMessage() | |||||
{ | |||||
if (ShouldSkipDbTests()) | |||||
{ | |||||
return; | |||||
} | |||||
var manager = CreateManager(); | |||||
var message = CreateTestSentMessage(); | |||||
var operateResult = await manager.StoreSentMessageAsync(message); | |||||
Assert.NotNull(operateResult); | |||||
Assert.True(operateResult.Succeeded); | |||||
var storeMessage = await manager.GetNextSentMessageToBeEnqueuedAsync(); | |||||
Assert.Equal(message, storeMessage); | |||||
} | |||||
} | |||||
} |