diff --git a/src/VirtoCommerce.Platform.Caching/PlatformMemoryCache.cs b/src/VirtoCommerce.Platform.Caching/PlatformMemoryCache.cs index b58b6d659c0..3cb5468052b 100644 --- a/src/VirtoCommerce.Platform.Caching/PlatformMemoryCache.cs +++ b/src/VirtoCommerce.Platform.Caching/PlatformMemoryCache.cs @@ -21,7 +21,7 @@ public PlatformMemoryCache(IMemoryCache memoryCache, IOptions op SlidingExpiration = cachingOptions.CacheSlidingExpiration; _log = log; } - + public virtual ICacheEntry CreateEntry(object key) { var result = _memoryCache.CreateEntry(key); @@ -88,7 +88,7 @@ public void Dispose() { Dispose(true); // This object will be cleaned up by the Dispose method. - // Therefore, you should call GC.SupressFinalize to + // Therefore, you should call GC.SuppressFinalize to // take this object off the finalization queue // and prevent finalization code for this object // from executing a second time. @@ -107,10 +107,10 @@ protected virtual void Dispose(bool disposing) } } - + protected virtual void EvictionCallback(object key, object value, EvictionReason reason, object state) { _log.LogTrace($"EvictionCallback: Cache entry with key:{key} has been removed."); - } + } } } diff --git a/src/VirtoCommerce.Platform.Core/Bus/HandlerWrapper.cs b/src/VirtoCommerce.Platform.Core/Bus/HandlerWrapper.cs index a3b7e94f2f7..80742bb69b2 100644 --- a/src/VirtoCommerce.Platform.Core/Bus/HandlerWrapper.cs +++ b/src/VirtoCommerce.Platform.Core/Bus/HandlerWrapper.cs @@ -8,9 +8,10 @@ namespace VirtoCommerce.Platform.Core.Bus { + [DebuggerDisplay("{HandlerModuleName} {EventType.Name}")] public sealed class HandlerWrapper { - public string EventName { get; set; } + public Type EventType { get; set; } public string HandlerModuleName { get; set; } @@ -26,8 +27,9 @@ public Task Handle(IEvent @event, CancellationToken cancellationToken) Handler(@event, cancellationToken).GetAwaiter().GetResult(); stopWatch.Stop(); - Logger.LogInformation($"event:{EventName} module:{HandlerModuleName} overall_elapsed:{stopWatch.ElapsedMilliseconds}"); - }); + Logger.LogInformation("event:{Event} module:{Handler} overall_elapsed:{Elapsed}", + @event.GetType().Name, HandlerModuleName, stopWatch.ElapsedMilliseconds); + }, cancellationToken); } } } diff --git a/src/VirtoCommerce.Platform.Core/Bus/IHandlerRegistrar.cs b/src/VirtoCommerce.Platform.Core/Bus/IHandlerRegistrar.cs index d18397606b1..011f8c5a300 100644 --- a/src/VirtoCommerce.Platform.Core/Bus/IHandlerRegistrar.cs +++ b/src/VirtoCommerce.Platform.Core/Bus/IHandlerRegistrar.cs @@ -7,6 +7,7 @@ namespace VirtoCommerce.Platform.Core.Bus { public interface IHandlerRegistrar { - void RegisterHandler(Func handler) where T : class, IMessage; + [Obsolete("Use IApplicationBuilder.RegisterEventHandler<>()", DiagnosticId = "VC0008", UrlFormat = "https://docs.virtocommerce.org/products/products-virto3-versions")] + void RegisterHandler(Func handler) where T : IMessage; } } diff --git a/src/VirtoCommerce.Platform.Core/Bus/InProcessBus.cs b/src/VirtoCommerce.Platform.Core/Bus/InProcessBus.cs index 5876afa0704..351b4a79a0b 100644 --- a/src/VirtoCommerce.Platform.Core/Bus/InProcessBus.cs +++ b/src/VirtoCommerce.Platform.Core/Bus/InProcessBus.cs @@ -9,40 +9,74 @@ namespace VirtoCommerce.Platform.Core.Bus { - public class InProcessBus : IEventPublisher, IHandlerRegistrar + public class InProcessBus : IEventHandlerRegistrar, IEventPublisher, IHandlerRegistrar { private readonly ILogger _logger; - private readonly Dictionary> _handlersByType = new Dictionary>(); + private readonly List _handlers = []; public InProcessBus(ILogger logger) { _logger = logger; } - public void RegisterHandler(Func handler) where T : class, IMessage + public void RegisterEventHandler(Func handler) + where T : IEvent { - if (!_handlersByType.TryGetValue(typeof(T), out var handlers)) + var eventType = typeof(T); + + var handlerWrapper = new HandlerWrapper { - handlers = new List(); - _handlersByType.Add(typeof(T), handlers); - } + EventType = eventType, + HandlerModuleName = handler.Target?.GetType().Module.Assembly.GetName().Name, + Handler = (message, _) => handler((T)message), + Logger = _logger + }; + + _handlers.Add(handlerWrapper); + } + + public void RegisterEventHandler(Func handler) + where T : IEvent + { +#pragma warning disable VC0008 // Type or member is obsolete + RegisterHandler(handler); +#pragma warning restore VC0008 // Type or member is obsolete + } + + [Obsolete("Use IApplicationBuilder.RegisterEventHandler<>()", DiagnosticId = "VC0008", UrlFormat = "https://docs.virtocommerce.org/products/products-virto3-versions")] + public void RegisterHandler(Func handler) + where T : IMessage + { + var eventType = typeof(T); var handlerWrapper = new HandlerWrapper { - EventName = typeof(T).Name, - HandlerModuleName = handler.Target.GetType().Module.Assembly.GetName().Name, + EventType = eventType, + HandlerModuleName = handler.Target?.GetType().Module.Assembly.GetName().Name, Handler = (message, token) => handler((T)message, token), Logger = _logger }; - handlers.Add(handlerWrapper); + _handlers.Add(handlerWrapper); } - public async Task Publish(T @event, CancellationToken cancellationToken = default(CancellationToken)) where T : class, IEvent + public async Task Publish(T @event, CancellationToken cancellationToken = default) + where T : IEvent { - if (!EventSuppressor.EventsSuppressed && _handlersByType.TryGetValue(@event.GetType(), out var handlers)) + if (EventSuppressor.EventsSuppressed) + { + return; + } + + var eventType = @event.GetType(); + + var handlers = _handlers + .Where(x => x.EventType.IsAssignableFrom(eventType)) + .ToList(); + + if (handlers.Count > 0) { - await Task.WhenAll(handlers.Select(handler => handler.Handle(@event, cancellationToken))); + await Task.WhenAll(handlers.Select(x => x.Handle(@event, cancellationToken))); } } } diff --git a/src/VirtoCommerce.Platform.Core/Events/ApplicationBuilderExtensions.cs b/src/VirtoCommerce.Platform.Core/Events/ApplicationBuilderExtensions.cs new file mode 100644 index 00000000000..8c1c5152b25 --- /dev/null +++ b/src/VirtoCommerce.Platform.Core/Events/ApplicationBuilderExtensions.cs @@ -0,0 +1,42 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; + +namespace VirtoCommerce.Platform.Core.Events; + +public static class ApplicationBuilderExtensions +{ + public static IApplicationBuilder RegisterEventHandler(this IApplicationBuilder applicationBuilder) + where TEvent : IEvent + where THandler : IEventHandler + { + var handler = applicationBuilder.ApplicationServices.GetRequiredService(); + return applicationBuilder.RegisterEventHandler(handler.Handle); + } + + public static IApplicationBuilder RegisterEventHandler(this IApplicationBuilder applicationBuilder, Func handler) + where TEvent : IEvent + { + var registrar = applicationBuilder.ApplicationServices.GetRequiredService(); + registrar.RegisterEventHandler(handler); + return applicationBuilder; + } + + public static IApplicationBuilder RegisterCancellableEventHandler(this IApplicationBuilder applicationBuilder) + where TEvent : IEvent + where THandler : ICancellableEventHandler + { + var handler = applicationBuilder.ApplicationServices.GetRequiredService(); + return applicationBuilder.RegisterCancellableEventHandler(handler.Handle); + } + + public static IApplicationBuilder RegisterCancellableEventHandler(this IApplicationBuilder applicationBuilder, Func handler) + where TEvent : IEvent + { + var registrar = applicationBuilder.ApplicationServices.GetRequiredService(); + registrar.RegisterEventHandler(handler); + return applicationBuilder; + } +} diff --git a/src/VirtoCommerce.Platform.Core/Events/EventSuppressor.cs b/src/VirtoCommerce.Platform.Core/Events/EventSuppressor.cs index ebf31dd720b..79809f3c4dd 100644 --- a/src/VirtoCommerce.Platform.Core/Events/EventSuppressor.cs +++ b/src/VirtoCommerce.Platform.Core/Events/EventSuppressor.cs @@ -31,20 +31,23 @@ private void Dispose(bool disposing) } } - private static readonly AsyncLocal EventsSuppressedStorage = new AsyncLocal(); + private static readonly AsyncLocal _eventsSuppressedStorage = new(); /// /// The flag indicates that events are suppressed for the current asynchronous control flow /// - public static bool EventsSuppressed => EventsSuppressedStorage.Value; + public static bool EventsSuppressed => _eventsSuppressedStorage.Value; + + [Obsolete("Use SuppressEvents()", DiagnosticId = "VC0008", UrlFormat = "https://docs.virtocommerce.org/products/products-virto3-versions/")] + public static IDisposable SupressEvents() => SuppressEvents(); /// /// The flag indicates that events are suppressed for the current asynchronous control flow /// - public static IDisposable SupressEvents() + public static IDisposable SuppressEvents() { - EventsSuppressedStorage.Value = true; - return new DisposableActionGuard(() => { EventsSuppressedStorage.Value = false; }); + _eventsSuppressedStorage.Value = true; + return new DisposableActionGuard(() => { _eventsSuppressedStorage.Value = false; }); } } } diff --git a/src/VirtoCommerce.Platform.Core/Events/IEventHandlerRegistrar.cs b/src/VirtoCommerce.Platform.Core/Events/IEventHandlerRegistrar.cs new file mode 100644 index 00000000000..3ea5a5a24ec --- /dev/null +++ b/src/VirtoCommerce.Platform.Core/Events/IEventHandlerRegistrar.cs @@ -0,0 +1,11 @@ +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace VirtoCommerce.Platform.Core.Events; + +public interface IEventHandlerRegistrar +{ + void RegisterEventHandler(Func handler) where T : IEvent; + void RegisterEventHandler(Func handler) where T : IEvent; +} diff --git a/src/VirtoCommerce.Platform.Core/Events/IEventPublisher.cs b/src/VirtoCommerce.Platform.Core/Events/IEventPublisher.cs index 164b2a0b1ce..4d1e495c75f 100644 --- a/src/VirtoCommerce.Platform.Core/Events/IEventPublisher.cs +++ b/src/VirtoCommerce.Platform.Core/Events/IEventPublisher.cs @@ -5,6 +5,6 @@ namespace VirtoCommerce.Platform.Core.Events { public interface IEventPublisher { - Task Publish(T @event, CancellationToken cancellationToken = default(CancellationToken)) where T : class, IEvent; + Task Publish(T @event, CancellationToken cancellationToken = default) where T : IEvent; } } diff --git a/src/VirtoCommerce.Platform.Data/ExportImport/PlatformExportImportManager.cs b/src/VirtoCommerce.Platform.Data/ExportImport/PlatformExportImportManager.cs index db535ec757d..6acd5e94eff 100644 --- a/src/VirtoCommerce.Platform.Data/ExportImport/PlatformExportImportManager.cs +++ b/src/VirtoCommerce.Platform.Data/ExportImport/PlatformExportImportManager.cs @@ -129,7 +129,7 @@ public async Task ImportAsync(Stream inputStream, PlatformExportManifest importO progressCallback(progressInfo); using (var zipArchive = new ZipArchive(inputStream, ZipArchiveMode.Read, true)) - using (EventSuppressor.SupressEvents()) + using (EventSuppressor.SuppressEvents()) { //Import selected platform entries await ImportPlatformEntriesInternalAsync(zipArchive, importOptions, progressCallback, сancellationToken); diff --git a/src/VirtoCommerce.Platform.Data/Extensions/ServiceCollectionExtensions.cs b/src/VirtoCommerce.Platform.Data/Extensions/ServiceCollectionExtensions.cs index a1ef99c70c7..6b46b34b3af 100644 --- a/src/VirtoCommerce.Platform.Data/Extensions/ServiceCollectionExtensions.cs +++ b/src/VirtoCommerce.Platform.Data/Extensions/ServiceCollectionExtensions.cs @@ -38,6 +38,7 @@ public static IServiceCollection AddPlatformServices(this IServiceCollection ser services.AddDynamicProperties(); services.AddSingleton(); + services.AddSingleton(x => x.GetRequiredService()); services.AddSingleton(x => x.GetRequiredService()); services.AddSingleton(x => x.GetRequiredService()); services.AddTransient(); diff --git a/src/VirtoCommerce.Platform.Hangfire/Extensions/ApplicationBuilderExtensions.cs b/src/VirtoCommerce.Platform.Hangfire/Extensions/ApplicationBuilderExtensions.cs index 2609327105b..c3bcbe3d51f 100644 --- a/src/VirtoCommerce.Platform.Hangfire/Extensions/ApplicationBuilderExtensions.cs +++ b/src/VirtoCommerce.Platform.Hangfire/Extensions/ApplicationBuilderExtensions.cs @@ -8,7 +8,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; -using VirtoCommerce.Platform.Core.Bus; +using VirtoCommerce.Platform.Core.Events; using VirtoCommerce.Platform.Core.Security; using VirtoCommerce.Platform.Core.Settings; using VirtoCommerce.Platform.Core.Settings.Events; @@ -61,10 +61,9 @@ public static IApplicationBuilder UseHangfire(this IApplicationBuilder appBuilde var mvcJsonOptions = appBuilder.ApplicationServices.GetService>(); GlobalConfiguration.Configuration.UseSerializerSettings(mvcJsonOptions.Value.SerializerSettings); - var inProcessBus = appBuilder.ApplicationServices.GetService(); var recurringJobManager = appBuilder.ApplicationServices.GetService(); var settingsManager = appBuilder.ApplicationServices.GetService(); - inProcessBus.RegisterHandler(async (message, token) => await recurringJobManager.HandleSettingChangeAsync(settingsManager, message)); + appBuilder.RegisterEventHandler(message => recurringJobManager.HandleSettingChangeAsync(settingsManager, message)); // Add Hangfire filters/middlewares var userNameResolver = appBuilder.ApplicationServices.CreateScope().ServiceProvider.GetRequiredService(); diff --git a/src/VirtoCommerce.Platform.Web/Security/ApplicationBuilderExtensions.cs b/src/VirtoCommerce.Platform.Web/Security/ApplicationBuilderExtensions.cs index b4d573ab644..82f8f5d44d6 100644 --- a/src/VirtoCommerce.Platform.Web/Security/ApplicationBuilderExtensions.cs +++ b/src/VirtoCommerce.Platform.Web/Security/ApplicationBuilderExtensions.cs @@ -3,8 +3,8 @@ using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using VirtoCommerce.Platform.Core; -using VirtoCommerce.Platform.Core.Bus; using VirtoCommerce.Platform.Core.Common; +using VirtoCommerce.Platform.Core.Events; using VirtoCommerce.Platform.Core.Security; using VirtoCommerce.Platform.Core.Security.Events; using VirtoCommerce.Platform.Core.Settings; @@ -29,15 +29,14 @@ public static IApplicationBuilder UsePlatformPermissions(this IApplicationBuilde public static IApplicationBuilder UseSecurityHandlers(this IApplicationBuilder appBuilder) { - var inProcessBus = appBuilder.ApplicationServices.GetService(); - inProcessBus.RegisterHandler(async (message, token) => await appBuilder.ApplicationServices.GetService().Handle(message)); - inProcessBus.RegisterHandler(async (message, token) => await appBuilder.ApplicationServices.GetService().Handle(message)); - inProcessBus.RegisterHandler(async (message, token) => await appBuilder.ApplicationServices.GetService().Handle(message)); - inProcessBus.RegisterHandler(async (message, token) => await appBuilder.ApplicationServices.GetService().Handle(message)); - inProcessBus.RegisterHandler(async (message, token) => await appBuilder.ApplicationServices.GetService().Handle(message)); - inProcessBus.RegisterHandler(async (message, token) => await appBuilder.ApplicationServices.GetService().Handle(message)); - inProcessBus.RegisterHandler(async (message, token) => await appBuilder.ApplicationServices.GetService().Handle(message)); - inProcessBus.RegisterHandler(async (message, token) => await appBuilder.ApplicationServices.GetService().Handle(message)); + appBuilder.RegisterEventHandler(); + appBuilder.RegisterEventHandler(); + appBuilder.RegisterEventHandler(); + appBuilder.RegisterEventHandler(); + appBuilder.RegisterEventHandler(); + appBuilder.RegisterEventHandler(); + appBuilder.RegisterEventHandler(); + appBuilder.RegisterEventHandler(); return appBuilder; } diff --git a/src/VirtoCommerce.Platform.Web/Security/ServiceCollectionExtensions.cs b/src/VirtoCommerce.Platform.Web/Security/ServiceCollectionExtensions.cs index fac6587cb55..785d9d2099c 100644 --- a/src/VirtoCommerce.Platform.Web/Security/ServiceCollectionExtensions.cs +++ b/src/VirtoCommerce.Platform.Web/Security/ServiceCollectionExtensions.cs @@ -4,7 +4,6 @@ using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; -using VirtoCommerce.Platform.Core.ChangeLog; using VirtoCommerce.Platform.Core.Common; using VirtoCommerce.Platform.Core.Security; using VirtoCommerce.Platform.Core.Security.Search; @@ -23,8 +22,8 @@ public static IServiceCollection AddSecurityServices(this IServiceCollection ser services.AddTransient(); services.AddTransient>(provider => () => provider.CreateScope().ServiceProvider.GetService()); - services.AddScoped(); - services.AddScoped(); + services.AddSingleton(); + services.AddSingleton(); services.AddScoped(); services.AddSingleton(); @@ -57,8 +56,8 @@ public static IServiceCollection AddSecurityServices(this IServiceCollection ser services.Configure(setupAction); } - services.AddSingleton(provider => new LogChangesUserChangedEventHandler(provider.CreateScope().ServiceProvider.GetService())); - services.AddSingleton(provider => new UserApiKeyActualizeEventHandler(provider.CreateScope().ServiceProvider.GetService())); + services.AddSingleton(); + services.AddSingleton(); services.AddTransient(); diff --git a/tests/VirtoCommerce.Platform.Tests/Common/CountriesServiceTests.cs b/tests/VirtoCommerce.Platform.Tests/Common/CountriesServiceTests.cs index aaf5c53d621..df4948a52bf 100644 --- a/tests/VirtoCommerce.Platform.Tests/Common/CountriesServiceTests.cs +++ b/tests/VirtoCommerce.Platform.Tests/Common/CountriesServiceTests.cs @@ -1,4 +1,5 @@ using System; +using System.Threading.Tasks; using Moq; using Nager.Country; using VirtoCommerce.Platform.Core.Common; @@ -10,12 +11,12 @@ namespace VirtoCommerce.Platform.Tests.Common public class CountriesServiceTests { [Fact] - public void CanGetCountries() + public async Task CanGetCountries() { var filesystemCountryService = new Mock(); var service = new CountriesService(filesystemCountryService.Object as FileSystemCountriesService); - var countries = service.GetCountriesAsync().GetAwaiter().GetResult(); + var countries = await service.GetCountriesAsync(); Assert.Equal(249, countries.Count); } diff --git a/tests/VirtoCommerce.Platform.Tests/Events/EventHandlerTests.cs b/tests/VirtoCommerce.Platform.Tests/Events/EventHandlerTests.cs new file mode 100644 index 00000000000..2fc7bf3a0eb --- /dev/null +++ b/tests/VirtoCommerce.Platform.Tests/Events/EventHandlerTests.cs @@ -0,0 +1,46 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using FluentAssertions; +using Microsoft.Extensions.Logging; +using Moq; +using VirtoCommerce.Platform.Core.Bus; +using VirtoCommerce.Platform.Core.Events; +using VirtoCommerce.Platform.Core.Security.Events; +using Xunit; + +namespace VirtoCommerce.Platform.Tests.Events; + +[Trait("Category", "Unit")] +public class EventHandlerTests +{ + [Fact] + public async Task HandleMultipleEventTypesWithSingleRegistration() + { + var bus = new InProcessBus(new Mock>().Object); + + var domainHandlerEvents = new List(); + var userLoginHandlerEvents = new List(); + var userChangedHandlerEvents = new List(); + + // This handler should handle all event types + bus.RegisterEventHandler(message => Handle(message, domainHandlerEvents)); + + // These handlers should handle only specific event types + bus.RegisterEventHandler(message => Handle(message, userLoginHandlerEvents)); + bus.RegisterEventHandler(message => Handle(message, userChangedHandlerEvents)); + + await bus.Publish(new UserLoginEvent(user: null)); + await bus.Publish(new UserChangedEvent(changedEntries: null)); + + domainHandlerEvents.Should().BeEquivalentTo([nameof(UserLoginEvent), nameof(UserChangedEvent)]); + userLoginHandlerEvents.Should().BeEquivalentTo([nameof(UserLoginEvent)]); + userChangedHandlerEvents.Should().BeEquivalentTo([nameof(UserChangedEvent)]); + } + + private static Task Handle(T message, List events) where T : IEvent + { + events.Add(message.GetType().Name); + + return Task.CompletedTask; + } +} diff --git a/tests/VirtoCommerce.Platform.Tests/Events/EventSuppressorTests.cs b/tests/VirtoCommerce.Platform.Tests/Events/EventSuppressorTests.cs index 9a2b0012ab4..ac97686c16d 100644 --- a/tests/VirtoCommerce.Platform.Tests/Events/EventSuppressorTests.cs +++ b/tests/VirtoCommerce.Platform.Tests/Events/EventSuppressorTests.cs @@ -6,14 +6,14 @@ namespace VirtoCommerce.Platform.Tests.Events { [Trait("Category", "Unit")] - public class EventSupressorTests + public class EventSuppressorTests { [Fact] public void SuppressInCurrentThread() { Assert.False(EventSuppressor.EventsSuppressed, "EventSuppressor shouldn't be active in this thread before test."); - using (EventSuppressor.SupressEvents()) + using (EventSuppressor.SuppressEvents()) { Assert.True(EventSuppressor.EventsSuppressed, "EventSuppressor should be active in this thread."); } @@ -22,18 +22,18 @@ public void SuppressInCurrentThread() } [Fact] - public void InheritedSuppressInAnotherThread() + public async Task InheritedSuppressInAnotherThread() { Assert.False(EventSuppressor.EventsSuppressed, "EventSuppressor shouldn't be active in this thread before test."); - using (EventSuppressor.SupressEvents()) + using (EventSuppressor.SuppressEvents()) { Assert.True(EventSuppressor.EventsSuppressed, "EventSuppressor should be active in this thread."); - Task.Run(() => + await Task.Run(() => { Assert.True(EventSuppressor.EventsSuppressed, "EventSuppressor inherits value in another thread!"); - }).Wait(); + }); } Assert.False(EventSuppressor.EventsSuppressed, "EventSuppressor shouldn't be active in this thread after test."); @@ -46,15 +46,15 @@ public async Task NotInheritedSetAfterAsyncMethodStarts() "EventSuppressor shouldn't be active in this thread before test."); var taskCompletionSource = new TaskCompletionSource(); - Func notInteritedAction = async () => + Func notInheritedAction = async () => { await taskCompletionSource.Task; Assert.False(EventSuppressor.EventsSuppressed, "EventSuppressor shouldn't be active in this thread."); }; - var checkTask = notInteritedAction(); + var checkTask = notInheritedAction(); - using (EventSuppressor.SupressEvents()) + using (EventSuppressor.SuppressEvents()) { Assert.True(EventSuppressor.EventsSuppressed, "EventSuppressor inherits value in another thread!"); taskCompletionSource.TrySetResult(null); @@ -65,7 +65,7 @@ public async Task NotInheritedSetAfterAsyncMethodStarts() } [Fact] - public void NotInheritedSetAfterAsyncMethodStartsInAnotherAsyncMethod() + public async Task NotInheritedSetAfterAsyncMethodStartsInAnotherAsyncMethod() { Assert.False(EventSuppressor.EventsSuppressed, "EventSuppressor shouldn't be active in this thread before test."); @@ -79,16 +79,16 @@ public void NotInheritedSetAfterAsyncMethodStartsInAnotherAsyncMethod() var checkTask = notInheritedAction(); - Task.Run(async () => + await Task.Run(async () => { - using (EventSuppressor.SupressEvents()) + using (EventSuppressor.SuppressEvents()) { Assert.True(EventSuppressor.EventsSuppressed, "EventSuppressor inherits value in another thread!"); taskCompletionSource.TrySetResult(null); await checkTask; } Assert.False(EventSuppressor.EventsSuppressed, "EventSuppressor shouldn't be active in this thread after test."); - }).Wait(); + }); Assert.False(EventSuppressor.EventsSuppressed, "EventSuppressor shouldn't be active in this thread after test."); }