From 3c2f51e8f875ae6677e833a9d6c9ca7693b78aee Mon Sep 17 00:00:00 2001 From: yangxiaodong Date: Wed, 28 Jun 2017 15:47:24 +0800 Subject: [PATCH] Add unit test --- .../ConnectionUtil.cs | 46 ++++ .../DatabaseTestHost.cs | 61 ++++++ .../DbUtil.cs | 2 +- .../DefaultPocoTest.cs | 112 +++++----- ...etCore.CAP.EntityFrameworkCore.Test.csproj | 1 + .../EnsuranceTest.cs | 12 + .../MessageStoreTest.cs | 193 ++++++++-------- .../MessageStoreWithGenericsTest.cs | 62 ------ .../TestHost.cs | 97 ++++++++ .../config.json | 2 +- .../DotNetCore.CAP.Test.csproj | 4 - .../Job/ComputedJobTest.cs | 56 +++++ .../Job/JobProcessingServerTest.cs | 185 ++++++++++++++++ test/Shared/MessageManagerTestBase.cs | 207 ++++++++++-------- 14 files changed, 734 insertions(+), 306 deletions(-) create mode 100644 test/DotNetCore.CAP.EntityFrameworkCore.Test/ConnectionUtil.cs create mode 100644 test/DotNetCore.CAP.EntityFrameworkCore.Test/DatabaseTestHost.cs create mode 100644 test/DotNetCore.CAP.EntityFrameworkCore.Test/EnsuranceTest.cs delete mode 100644 test/DotNetCore.CAP.EntityFrameworkCore.Test/MessageStoreWithGenericsTest.cs create mode 100644 test/DotNetCore.CAP.EntityFrameworkCore.Test/TestHost.cs create mode 100644 test/DotNetCore.CAP.Test/Job/ComputedJobTest.cs create mode 100644 test/DotNetCore.CAP.Test/Job/JobProcessingServerTest.cs diff --git a/test/DotNetCore.CAP.EntityFrameworkCore.Test/ConnectionUtil.cs b/test/DotNetCore.CAP.EntityFrameworkCore.Test/ConnectionUtil.cs new file mode 100644 index 0000000..9a834ab --- /dev/null +++ b/test/DotNetCore.CAP.EntityFrameworkCore.Test/ConnectionUtil.cs @@ -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; + } + } +} diff --git a/test/DotNetCore.CAP.EntityFrameworkCore.Test/DatabaseTestHost.cs b/test/DotNetCore.CAP.EntityFrameworkCore.Test/DatabaseTestHost.cs new file mode 100644 index 0000000..9b69e25 --- /dev/null +++ b/test/DotNetCore.CAP.EntityFrameworkCore.Test/DatabaseTestHost.cs @@ -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(); + context.Database.EnsureDeleted(); + context.Database.Migrate(); + _sqlObjectInstalled = true; + } + } + } + + private void DeleteAllData() + { + using (CreateScope()) + { + var context = GetService(); + + 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); + } + } + } + } +} diff --git a/test/DotNetCore.CAP.EntityFrameworkCore.Test/DbUtil.cs b/test/DotNetCore.CAP.EntityFrameworkCore.Test/DbUtil.cs index d5fd010..ec747db 100644 --- a/test/DotNetCore.CAP.EntityFrameworkCore.Test/DbUtil.cs +++ b/test/DotNetCore.CAP.EntityFrameworkCore.Test/DbUtil.cs @@ -7,7 +7,7 @@ namespace DotNetCore.CAP.EntityFrameworkCore.Test public static class DbUtil { public static IServiceCollection ConfigureDbServices(string connectionString, IServiceCollection services = null) { - return ConfigureDbServices(connectionString, services); + return ConfigureDbServices(connectionString, services); } public static IServiceCollection ConfigureDbServices(string connectionString, IServiceCollection services = null) where TContext : DbContext { diff --git a/test/DotNetCore.CAP.EntityFrameworkCore.Test/DefaultPocoTest.cs b/test/DotNetCore.CAP.EntityFrameworkCore.Test/DefaultPocoTest.cs index da9d022..f662932 100644 --- a/test/DotNetCore.CAP.EntityFrameworkCore.Test/DefaultPocoTest.cs +++ b/test/DotNetCore.CAP.EntityFrameworkCore.Test/DefaultPocoTest.cs @@ -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 -// { -// private readonly ApplicationBuilder _builder; - -// public DefaultPocoTest(ScratchDatabaseFixture fixture) { -// var services = new ServiceCollection(); - -// services -// .AddDbContext(o => o.UseSqlServer(fixture.ConnectionString)) -// .AddConsistency() -// .AddEntityFrameworkStores(); - -// services.AddLogging(); - -// var provider = services.BuildServiceProvider(); -// _builder = new ApplicationBuilder(provider); - -// using (var scoped = provider.GetRequiredService().CreateScope()) -// using (var db = scoped.ServiceProvider.GetRequiredService()) { -// db.Database.EnsureCreated(); -// } -// } - -// [ConditionalFact] -// [FrameworkSkipCondition(RuntimeFrameworks.Mono)] -// [OSSkipCondition(OperatingSystems.Linux)] -// [OSSkipCondition(OperatingSystems.MacOSX)] -// public async Task EnsureStartupUsageWorks() { -// var messageStore = _builder.ApplicationServices.GetRequiredService(); -// var messageManager = _builder.ApplicationServices.GetRequiredService(); - -// 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); -// } -// } -//} \ No newline at end of file +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 + { + private readonly ApplicationBuilder _builder; + + public DefaultPocoTest(ScratchDatabaseFixture fixture) + { + var services = new ServiceCollection(); + + services + .AddDbContext(o => o.UseSqlServer(fixture.ConnectionString)) + .AddConsistency() + .AddEntityFrameworkStores(); + + services.AddLogging(); + + var provider = services.BuildServiceProvider(); + _builder = new ApplicationBuilder(provider); + + using (var scoped = provider.GetRequiredService().CreateScope()) + using (var db = scoped.ServiceProvider.GetRequiredService()) + { + db.Database.EnsureCreated(); + } + } + + [ConditionalFact] + [FrameworkSkipCondition(RuntimeFrameworks.Mono)] + [OSSkipCondition(OperatingSystems.Linux)] + [OSSkipCondition(OperatingSystems.MacOSX)] + public async Task EnsureStartupUsageWorks() + { + var messageStore = _builder.ApplicationServices.GetRequiredService(); + var messageManager = _builder.ApplicationServices.GetRequiredService(); + + 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); + } + } +} \ No newline at end of file diff --git a/test/DotNetCore.CAP.EntityFrameworkCore.Test/DotNetCore.CAP.EntityFrameworkCore.Test.csproj b/test/DotNetCore.CAP.EntityFrameworkCore.Test/DotNetCore.CAP.EntityFrameworkCore.Test.csproj index 33af123..db49cdf 100644 --- a/test/DotNetCore.CAP.EntityFrameworkCore.Test/DotNetCore.CAP.EntityFrameworkCore.Test.csproj +++ b/test/DotNetCore.CAP.EntityFrameworkCore.Test/DotNetCore.CAP.EntityFrameworkCore.Test.csproj @@ -23,6 +23,7 @@ + diff --git a/test/DotNetCore.CAP.EntityFrameworkCore.Test/EnsuranceTest.cs b/test/DotNetCore.CAP.EntityFrameworkCore.Test/EnsuranceTest.cs new file mode 100644 index 0000000..2b010cd --- /dev/null +++ b/test/DotNetCore.CAP.EntityFrameworkCore.Test/EnsuranceTest.cs @@ -0,0 +1,12 @@ +using Xunit; + +namespace DotNetCore.CAP.EntityFrameworkCore.Test +{ + public class EnsuranceTest : DatabaseTestHost + { + [Fact] + public void Ensure() + { + } + } +} diff --git a/test/DotNetCore.CAP.EntityFrameworkCore.Test/MessageStoreTest.cs b/test/DotNetCore.CAP.EntityFrameworkCore.Test/MessageStoreTest.cs index dbc70ad..a0262c3 100644 --- a/test/DotNetCore.CAP.EntityFrameworkCore.Test/MessageStoreTest.cs +++ b/test/DotNetCore.CAP.EntityFrameworkCore.Test/MessageStoreTest.cs @@ -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, IClassFixture -// { -// private readonly ScratchDatabaseFixture _fixture; +namespace DotNetCore.CAP.EntityFrameworkCore.Test +{ + public class MessageStoreTest : MessageManagerTestBase, IClassFixture + { + 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 options) : base(options) { -// } -// } + public class ApplicationDbContext : CapDbContext + { + public ApplicationDbContext(DbContextOptions 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(_fixture.ConnectionString); -// if (delete) { -// db.Database.EnsureDeleted(); -// } -// db.Database.EnsureCreated(); -// return db; -// } + public CapDbContext CreateContext(bool delete = false) + { + var db = DbUtil.Create(_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(new CapMessageStore((CapDbContext)context)); + } -// protected override void AddMessageStore(IServiceCollection services, object context = null) { -// services.AddSingleton(new ConsistencyMessageStore((ConsistencyDbContext)context)); -// } -// } + protected override CapSentMessage CreateTestSentMessage(string content = "") + { + return new CapSentMessage + { + Content = content + }; + } -// public class ApplicationMessage : ConsistencyMessage { } -//} \ No newline at end of file + protected override CapReceivedMessage CreateTestReceivedMessage(string content = "") + { + return new CapReceivedMessage() + { + Content = content + }; + } + } +} \ No newline at end of file diff --git a/test/DotNetCore.CAP.EntityFrameworkCore.Test/MessageStoreWithGenericsTest.cs b/test/DotNetCore.CAP.EntityFrameworkCore.Test/MessageStoreWithGenericsTest.cs deleted file mode 100644 index e99ee6a..0000000 --- a/test/DotNetCore.CAP.EntityFrameworkCore.Test/MessageStoreWithGenericsTest.cs +++ /dev/null @@ -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, IClassFixture -// { -// private readonly ScratchDatabaseFixture _fixture; - -// public MessageStoreWithGenericsTest(ScratchDatabaseFixture fixture) { -// _fixture = fixture; -// } - -// protected override void AddMessageStore(IServiceCollection services, object context = null) { -// services.AddSingleton(new MessageStoreWithGenerics((ContextWithGenerics)context)); -// } - -// protected override object CreateTestContext() { -// return CreateContext(); -// } - -// public ContextWithGenerics CreateContext() { -// var db = DbUtil.Create(_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 -// { -// public MessageStoreWithGenerics(ContextWithGenerics context) : base(context) { -// } -// } - -// public class ContextWithGenerics : ConsistencyDbContext -// { -// public ContextWithGenerics() { -// } -// } -//} \ No newline at end of file diff --git a/test/DotNetCore.CAP.EntityFrameworkCore.Test/TestHost.cs b/test/DotNetCore.CAP.EntityFrameworkCore.Test/TestHost.cs new file mode 100644 index 0000000..ba66382 --- /dev/null +++ b/test/DotNetCore.CAP.EntityFrameworkCore.Test/TestHost.cs @@ -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(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().CreateScope(); + return scope; + } + + public T GetService() => Provider.GetService(); + + public T Ensure(ref T service) + where T : class + => service ?? (service = GetService()); + + 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(); + } + } + } +} diff --git a/test/DotNetCore.CAP.EntityFrameworkCore.Test/config.json b/test/DotNetCore.CAP.EntityFrameworkCore.Test/config.json index a2fe7bc..9433626 100644 --- a/test/DotNetCore.CAP.EntityFrameworkCore.Test/config.json +++ b/test/DotNetCore.CAP.EntityFrameworkCore.Test/config.json @@ -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" } } } \ No newline at end of file diff --git a/test/DotNetCore.CAP.Test/DotNetCore.CAP.Test.csproj b/test/DotNetCore.CAP.Test/DotNetCore.CAP.Test.csproj index 58fb6f1..47cebe2 100644 --- a/test/DotNetCore.CAP.Test/DotNetCore.CAP.Test.csproj +++ b/test/DotNetCore.CAP.Test/DotNetCore.CAP.Test.csproj @@ -32,8 +32,4 @@ - - - - diff --git a/test/DotNetCore.CAP.Test/Job/ComputedJobTest.cs b/test/DotNetCore.CAP.Test/Job/ComputedJobTest.cs new file mode 100644 index 0000000..2772cf8 --- /dev/null +++ b/test/DotNetCore.CAP.Test/Job/ComputedJobTest.cs @@ -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); + } + } +} diff --git a/test/DotNetCore.CAP.Test/Job/JobProcessingServerTest.cs b/test/DotNetCore.CAP.Test/Job/JobProcessingServerTest.cs new file mode 100644 index 0000000..231c5b7 --- /dev/null +++ b/test/DotNetCore.CAP.Test/Job/JobProcessingServerTest.cs @@ -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 _mockStorage; + + public JobProcessingServerTest() + { + _options = new CapOptions() + { + PollingDelay = 0 + }; + _mockStorage = new Mock(); + _cancellationTokenSource = new CancellationTokenSource(); + + var services = new ServiceCollection(); + services.AddTransient(); + services.AddTransient(); + 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(() => 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(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(), It.IsAny())); + // 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(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(), It.IsAny())) + // .Throws(); + + // 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(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(), It.IsAny())); + // mockFetchedJob.Verify(m => m.RemoveFromQueue()); + //} + + //[Fact] + //public async Task ProcessAsync_JobThrows_WithNoRetry() + //{ + // // Arrange + // var job = new Job( + // InvocationData.Serialize( + // MethodInvocation.FromExpression(j => j.Throw())).Serialize()); + + // var mockFetchedJob = Mock.Get(Mock.Of(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(), It.IsAny())); + //} + + private JobProcessingServer Create() + => _provider.GetService(); + + //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(); } + //} + } +} diff --git a/test/Shared/MessageManagerTestBase.cs b/test/Shared/MessageManagerTestBase.cs index 4766bf5..d46b93b 100644 --- a/test/Shared/MessageManagerTestBase.cs +++ b/test/Shared/MessageManagerTestBase.cs @@ -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 : MessageManagerTestBase -// where TMessage : ConsistencyMessage -// { -// } - -// public abstract class MessageManagerTestBase -// where TMessage : ConsistencyMessage -// where TKey : IEquatable -// { -// private const string NullValue = "(null)"; - -// protected virtual bool ShouldSkipDbTests() { -// return false; -// } - -// protected virtual void SetupMessageServices(IServiceCollection services, object context = null) { -// services.AddSingleton(); -// services.AddConsistency(); -// AddMessageStore(services, context); - -// services.AddSingleton>(new TestLogger()); -// } - -// protected virtual IConsistencyMessageStore CreateManager(object context = null, IServiceCollection services = null, Action configureServices = null) { -// if (services == null) { -// services = new ServiceCollection(); -// } -// if (context == null) { -// context = CreateTestContext(); -// } -// SetupMessageServices(services, context); - -// configureServices?.Invoke(services); - -// return services.BuildServiceProvider().GetService(); -// } - -// 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)); -// } -// } - -//} \ No newline at end of file +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(); + services.AddConsistency(); + AddMessageStore(services, context); + + services.AddSingleton>(new TestLogger()); + } + + protected virtual ICapMessageStore CreateManager(object context = null, IServiceCollection services = null, Action configureServices = null) + { + if (services == null) + { + services = new ServiceCollection(); + } + if (context == null) + { + context = CreateTestContext(); + } + SetupMessageServices(services, context); + + configureServices?.Invoke(services); + + return services.BuildServiceProvider().GetService(); + } + + 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); + } + } + +} \ No newline at end of file