@@ -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 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 { | |||
@@ -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> | |||
<PackageReference Include="Dapper" Version="1.50.2" /> | |||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" /> | |||
<PackageReference Include="xunit.runner.visualstudio" 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": { | |||
"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}" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<Folder Include="Job\" /> | |||
</ItemGroup> | |||
</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); | |||
} | |||
} | |||
} |