mirror of https://github.com/abpframework/abp.git
14 changed files with 371 additions and 109 deletions
@ -0,0 +1,43 @@ |
|||
using System; |
|||
using MongoDB.Bson; |
|||
using MongoDB.Bson.Serialization; |
|||
using MongoDB.Bson.Serialization.Serializers; |
|||
|
|||
namespace Volo.Abp.MongoDB |
|||
{ |
|||
public class AbpMongoDbDateTimeSerializer : DateTimeSerializer |
|||
{ |
|||
protected DateTimeKind DateTimeKind { get; set; } |
|||
protected bool DisableDateTimeNormalization{ get; set; } |
|||
|
|||
public AbpMongoDbDateTimeSerializer(DateTimeKind dateTimeKind , bool disableDateTimeNormalization) |
|||
{ |
|||
DateTimeKind = dateTimeKind; |
|||
DisableDateTimeNormalization = disableDateTimeNormalization; |
|||
} |
|||
|
|||
public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, DateTime value) |
|||
{ |
|||
context.Writer.WriteDateTime(DisableDateTimeNormalization |
|||
? ToMillisecondsSinceEpoch(value) |
|||
: ToMillisecondsSinceEpoch(DateTime.SpecifyKind(value, DateTimeKind))); |
|||
} |
|||
|
|||
public override DateTime Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) |
|||
{ |
|||
var dateTime = new BsonDateTime(context.Reader.ReadDateTime()).ToUniversalTime(); |
|||
return DateTime.SpecifyKind(dateTime, DisableDateTimeNormalization ? DateTimeKind.Unspecified : DateTimeKind); |
|||
} |
|||
|
|||
private static long ToMillisecondsSinceEpoch(DateTime dateTime) |
|||
{ |
|||
return (dateTime - BsonConstants.UnixEpoch).Ticks / 10000L; |
|||
} |
|||
|
|||
// For unit testing.
|
|||
internal void SetDateTimeKind(DateTimeKind dateTimeKind) |
|||
{ |
|||
DateTimeKind = dateTimeKind; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
using Microsoft.EntityFrameworkCore; |
|||
using Microsoft.EntityFrameworkCore.Infrastructure; |
|||
|
|||
namespace Volo.Abp.EntityFrameworkCore |
|||
{ |
|||
/// <summary>
|
|||
/// Avoid unit test caching the configure of the entity.
|
|||
/// OnModelCreating will be executed multiple times
|
|||
/// </summary>
|
|||
public class UnitTestModelCacheKeyFactory : IModelCacheKeyFactory |
|||
{ |
|||
public object Create(DbContext context) |
|||
{ |
|||
return context; |
|||
} |
|||
} |
|||
} |
|||
@ -1,9 +0,0 @@ |
|||
using Volo.Abp.TestApp.Testing; |
|||
|
|||
namespace Volo.Abp.EntityFrameworkCore.ValueConverters |
|||
{ |
|||
public class AbpDateTimeValueConverter_Tests : AbpDateTimeValueConverter_Tests<AbpEntityFrameworkCoreTestModule> |
|||
{ |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,66 @@ |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Shouldly; |
|||
using Volo.Abp.TestApp.Domain; |
|||
using Volo.Abp.TestApp.Testing; |
|||
using Volo.Abp.Timing; |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.EntityFrameworkCore.ValueConverters |
|||
{ |
|||
public abstract class EFCore_DateTimeKindTests : DateTimeKind_Tests<AbpEntityFrameworkCoreTestModule> |
|||
{ |
|||
[Fact] |
|||
public async Task DateTime_Kind_Should_Be_Normalized_In_View_Query_Test() |
|||
{ |
|||
var personName = "bob lee"; |
|||
await PersonRepository.InsertAsync(new Person(Guid.NewGuid(), personName, 18) |
|||
{ |
|||
Birthday = DateTime.Parse("2020-01-01 00:00:00"), |
|||
LastActive = DateTime.Parse("2020-01-01 00:00:00"), |
|||
}, true); |
|||
|
|||
var person = await PersonRepository.GetViewAsync(personName); |
|||
|
|||
person.ShouldNotBeNull(); |
|||
person.CreationTime.Kind.ShouldBe(Kind); |
|||
|
|||
person.Birthday.ShouldNotBeNull(); |
|||
person.Birthday.Value.Kind.ShouldBe(Kind); |
|||
person.Birthday.Value.ToString("yyy-MM-dd HH:mm:ss").ShouldBe("2020-01-01 00:00:00"); |
|||
|
|||
//LastActive DisableDateTimeNormalization
|
|||
person.LastActive.ShouldNotBeNull(); |
|||
person.LastActive.Value.Kind.ShouldBe(DateTimeKind.Unspecified); |
|||
person.LastActive.Value.ToString("yyy-MM-dd HH:mm:ss").ShouldBe("2020-01-01 00:00:00"); |
|||
} |
|||
} |
|||
|
|||
public class DateTimeKindTests : EFCore_DateTimeKindTests |
|||
{ |
|||
protected override void AfterAddApplication(IServiceCollection services) |
|||
{ |
|||
Kind = DateTimeKind.Unspecified; |
|||
services.Configure<AbpClockOptions>(x => x.Kind = Kind); |
|||
} |
|||
} |
|||
|
|||
public class DateTimeKindTests_Local : EFCore_DateTimeKindTests |
|||
{ |
|||
protected override void AfterAddApplication(IServiceCollection services) |
|||
{ |
|||
Kind = DateTimeKind.Local; |
|||
services.Configure<AbpClockOptions>(x => x.Kind = Kind); |
|||
} |
|||
} |
|||
|
|||
public class DateTimeKindTests_Utc : EFCore_DateTimeKindTests |
|||
{ |
|||
protected override void AfterAddApplication(IServiceCollection services) |
|||
{ |
|||
Kind = DateTimeKind.Utc; |
|||
services.Configure<AbpClockOptions>(x => x.Kind = Kind); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,81 @@ |
|||
using System; |
|||
using System.Reflection; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using MongoDB.Bson.Serialization; |
|||
using MongoDB.Bson.Serialization.Serializers; |
|||
using Volo.Abp.TestApp.Testing; |
|||
using Volo.Abp.Timing; |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.MongoDB.Serializer |
|||
{ |
|||
[Collection(MongoTestCollection.Name)] |
|||
public abstract class MongoDB_DateTimeKind_Tests : DateTimeKind_Tests<AbpMongoDbTestModule>, IDisposable |
|||
{ |
|||
protected override void AfterAddApplication(IServiceCollection services) |
|||
{ |
|||
// MongoDB uses static properties to store the mapping information,
|
|||
// We must reconfigure it in the new unit test.
|
|||
foreach (var registeredClassMap in BsonClassMap.GetRegisteredClassMaps()) |
|||
{ |
|||
var frozen = registeredClassMap.GetType().BaseType?.GetField("_frozen", BindingFlags.NonPublic | BindingFlags.Instance); |
|||
frozen?.SetValue(registeredClassMap, false); |
|||
|
|||
foreach (var declaredMemberMap in registeredClassMap.DeclaredMemberMaps) |
|||
{ |
|||
var serializer = declaredMemberMap.GetSerializer(); |
|||
switch (serializer) |
|||
{ |
|||
case AbpMongoDbDateTimeSerializer dateTimeSerializer: |
|||
dateTimeSerializer.SetDateTimeKind(Kind); |
|||
break; |
|||
case NullableSerializer<DateTime> nullableSerializer: |
|||
{ |
|||
var lazySerializer = nullableSerializer.GetType() |
|||
?.GetField("_lazySerializer", BindingFlags.NonPublic | BindingFlags.Instance) |
|||
?.GetValue(serializer)?.As<Lazy<IBsonSerializer<DateTime>>>(); |
|||
|
|||
if (lazySerializer?.Value is AbpMongoDbDateTimeSerializer dateTimeSerializer) |
|||
{ |
|||
dateTimeSerializer.SetDateTimeKind(Kind); |
|||
} |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
frozen?.SetValue(registeredClassMap, true); |
|||
} |
|||
} |
|||
} |
|||
|
|||
public class DateTimeKindTests_Unspecified : MongoDB_DateTimeKind_Tests |
|||
{ |
|||
protected override void AfterAddApplication(IServiceCollection services) |
|||
{ |
|||
Kind = DateTimeKind.Unspecified; |
|||
services.Configure<AbpClockOptions>(x => x.Kind = Kind); |
|||
base.AfterAddApplication(services); |
|||
} |
|||
} |
|||
|
|||
public class DateTimeKindTests_Local : MongoDB_DateTimeKind_Tests |
|||
{ |
|||
protected override void AfterAddApplication(IServiceCollection services) |
|||
{ |
|||
Kind = DateTimeKind.Local; |
|||
services.Configure<AbpClockOptions>(x => x.Kind = Kind); |
|||
base.AfterAddApplication(services); |
|||
} |
|||
} |
|||
|
|||
public class DateTimeKindTests_Utc : MongoDB_DateTimeKind_Tests |
|||
{ |
|||
protected override void AfterAddApplication(IServiceCollection services) |
|||
{ |
|||
Kind = DateTimeKind.Utc; |
|||
services.Configure<AbpClockOptions>(x => x.Kind = Kind); |
|||
base.AfterAddApplication(services); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,30 @@ |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using MongoDB.Driver; |
|||
using Volo.Abp.Domain.Repositories.MongoDB; |
|||
using Volo.Abp.MongoDB; |
|||
using Volo.Abp.TestApp.Domain; |
|||
|
|||
namespace Volo.Abp.TestApp.MongoDB |
|||
{ |
|||
public class PersonRepository : MongoDbRepository<ITestAppMongoDbContext, Person, Guid>, IPersonRepository |
|||
{ |
|||
public PersonRepository(IMongoDbContextProvider<ITestAppMongoDbContext> dbContextProvider) |
|||
: base(dbContextProvider) |
|||
{ |
|||
|
|||
} |
|||
|
|||
public async Task<PersonView> GetViewAsync(string name) |
|||
{ |
|||
var person = await (await (await GetCollectionAsync()).FindAsync(x => x.Name == name)).FirstOrDefaultAsync(); |
|||
return new PersonView() |
|||
{ |
|||
Name = person.Name, |
|||
CreationTime = person.CreationTime, |
|||
Birthday = person.Birthday, |
|||
LastActive = person.LastActive |
|||
}; |
|||
} |
|||
} |
|||
} |
|||
@ -1,73 +0,0 @@ |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Shouldly; |
|||
using Volo.Abp.Domain.Repositories; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.TestApp.Domain; |
|||
using Volo.Abp.Timing; |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.TestApp.Testing |
|||
{ |
|||
public abstract class AbpDateTimeValueConverter_Tests<TStartupModule> : TestAppTestBase<TStartupModule> |
|||
where TStartupModule : IAbpModule |
|||
{ |
|||
private readonly IPersonRepository _personRepository; |
|||
|
|||
protected AbpDateTimeValueConverter_Tests() |
|||
{ |
|||
_personRepository = GetRequiredService<IPersonRepository>(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task DateTime_Kind_Should_Be_Normalized_To_UTC_Test() |
|||
{ |
|||
var personId = Guid.Parse("4125582e-d100-4c27-aa84-e4de85830dca"); |
|||
await _personRepository.InsertAsync(new Person(personId, "bob lee", 18) |
|||
{ |
|||
Birthday = DateTime.Parse("2020-01-01 00:00:00"), |
|||
LastActive = DateTime.Parse("2020-01-01 00:00:00"), |
|||
}, true); |
|||
|
|||
var person = await _personRepository.GetAsync(personId); |
|||
|
|||
person.ShouldNotBeNull(); |
|||
person.CreationTime.Kind.ShouldBe(DateTimeKind.Utc); |
|||
|
|||
person.Birthday.ShouldNotBeNull(); |
|||
person.Birthday.Value.Kind.ShouldBe(DateTimeKind.Utc); |
|||
person.Birthday.Value.ToString("yyy-MM-dd HH:mm:ss").ShouldBe("2020-01-01 00:00:00"); |
|||
|
|||
//LastActive DisableDateTimeNormalization
|
|||
person.LastActive.ShouldNotBeNull(); |
|||
person.LastActive.Value.Kind.ShouldBe(DateTimeKind.Unspecified); |
|||
person.LastActive.Value.ToString("yyy-MM-dd HH:mm:ss").ShouldBe("2020-01-01 00:00:00"); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task DateTime_Kind_Should_Be_Normalized_To_UTC_View_Test() |
|||
{ |
|||
var personName = "bob lee"; |
|||
await _personRepository.InsertAsync(new Person(Guid.NewGuid(), personName, 18) |
|||
{ |
|||
Birthday = DateTime.Parse("2020-01-01 00:00:00"), |
|||
LastActive = DateTime.Parse("2020-01-01 00:00:00"), |
|||
}, true); |
|||
|
|||
var person = await _personRepository.GetViewAsync(personName); |
|||
|
|||
person.ShouldNotBeNull(); |
|||
person.CreationTime.Kind.ShouldBe(DateTimeKind.Utc); |
|||
|
|||
person.Birthday.ShouldNotBeNull(); |
|||
person.Birthday.Value.Kind.ShouldBe(DateTimeKind.Utc); |
|||
person.Birthday.Value.ToString("yyy-MM-dd HH:mm:ss").ShouldBe("2020-01-01 00:00:00"); |
|||
|
|||
//LastActive DisableDateTimeNormalization
|
|||
person.LastActive.ShouldNotBeNull(); |
|||
person.LastActive.Value.Kind.ShouldBe(DateTimeKind.Unspecified); |
|||
person.LastActive.Value.ToString("yyy-MM-dd HH:mm:ss").ShouldBe("2020-01-01 00:00:00"); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,46 @@ |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Shouldly; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.TestApp.Domain; |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.TestApp.Testing |
|||
{ |
|||
public abstract class DateTimeKind_Tests<TStartupModule> : TestAppTestBase<TStartupModule> |
|||
where TStartupModule : IAbpModule |
|||
{ |
|||
protected IPersonRepository PersonRepository { get; } |
|||
protected DateTimeKind Kind { get; set; } |
|||
|
|||
protected DateTimeKind_Tests() |
|||
{ |
|||
PersonRepository = GetRequiredService<IPersonRepository>(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task DateTime_Kind_Should_Be_Normalized_Test() |
|||
{ |
|||
var personId = Guid.NewGuid(); |
|||
await PersonRepository.InsertAsync(new Person(personId, "bob lee", 18) |
|||
{ |
|||
Birthday = DateTime.Parse("2020-01-01 00:00:00"), |
|||
LastActive = DateTime.Parse("2020-01-01 00:00:00"), |
|||
}, true); |
|||
|
|||
var person = await PersonRepository.GetAsync(personId); |
|||
|
|||
person.ShouldNotBeNull(); |
|||
person.CreationTime.Kind.ShouldBe(Kind); |
|||
|
|||
person.Birthday.ShouldNotBeNull(); |
|||
person.Birthday.Value.Kind.ShouldBe(Kind); |
|||
person.Birthday.Value.ToString("yyy-MM-dd HH:mm:ss").ShouldBe("2020-01-01 00:00:00"); |
|||
|
|||
//LastActive DisableDateTimeNormalization
|
|||
person.LastActive.ShouldNotBeNull(); |
|||
person.LastActive.Value.Kind.ShouldBe(DateTimeKind.Unspecified); |
|||
person.LastActive.Value.ToString("yyy-MM-dd HH:mm:ss").ShouldBe("2020-01-01 00:00:00"); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue