Commit 9d37dc7f authored by Savorboard's avatar Savorboard

Add unit tests for ConsumerInvoker

parent a7080292
...@@ -22,6 +22,7 @@ namespace Microsoft.Extensions.DependencyInjection ...@@ -22,6 +22,7 @@ namespace Microsoft.Extensions.DependencyInjection
public static class ServiceCollectionExtensions public static class ServiceCollectionExtensions
{ {
internal static IServiceCollection ServiceCollection; internal static IServiceCollection ServiceCollection;
/// <summary> /// <summary>
/// Adds and configures the consistence services for the consistency. /// Adds and configures the consistence services for the consistency.
/// </summary> /// </summary>
......
// Copyright (c) .NET Core Community. All rights reserved. // Copyright (c) .NET Core Community. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information. // Licensed under the MIT License. See License.txt in the project root for license information.
using System; using System;
using System.Linq; using System.Linq;
using System.Reflection; using System.Threading.Tasks;
using System.Threading.Tasks; using DotNetCore.CAP.Abstractions;
using DotNetCore.CAP.Abstractions; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Internal;
using Microsoft.Extensions.Internal; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging;
namespace DotNetCore.CAP.Internal
namespace DotNetCore.CAP.Internal {
{ internal class DefaultConsumerInvoker : IConsumerInvoker
internal class DefaultConsumerInvoker : IConsumerInvoker {
{ private readonly ILogger _logger;
private readonly ILogger _logger; private readonly IMessagePacker _messagePacker;
private readonly IMessagePacker _messagePacker; private readonly IModelBinderFactory _modelBinderFactory;
private readonly IModelBinderFactory _modelBinderFactory; private readonly IServiceProvider _serviceProvider;
private readonly IServiceProvider _serviceProvider;
public DefaultConsumerInvoker(ILoggerFactory loggerFactory,
public DefaultConsumerInvoker(ILoggerFactory loggerFactory, IServiceProvider serviceProvider,
IServiceProvider serviceProvider, IMessagePacker messagePacker,
IMessagePacker messagePacker, IModelBinderFactory modelBinderFactory)
IModelBinderFactory modelBinderFactory) {
{ _modelBinderFactory = modelBinderFactory;
_modelBinderFactory = modelBinderFactory; _serviceProvider = serviceProvider;
_serviceProvider = serviceProvider; _messagePacker = messagePacker;
_messagePacker = messagePacker; _logger = loggerFactory.CreateLogger<DefaultConsumerInvoker>();
_logger = loggerFactory.CreateLogger<DefaultConsumerInvoker>(); }
}
public async Task<ConsumerExecutedResult> InvokeAsync(ConsumerContext context)
public async Task<ConsumerExecutedResult> InvokeAsync(ConsumerContext context) {
{ _logger.LogDebug("Executing consumer Topic: {0}", context.ConsumerDescriptor.MethodInfo.Name);
_logger.LogDebug("Executing consumer Topic: {0}", context.ConsumerDescriptor.MethodInfo.Name);
var executor = ObjectMethodExecutor.Create(
var executor = ObjectMethodExecutor.Create( context.ConsumerDescriptor.MethodInfo,
context.ConsumerDescriptor.MethodInfo, context.ConsumerDescriptor.ImplTypeInfo);
context.ConsumerDescriptor.ImplTypeInfo);
using (var scope = _serviceProvider.CreateScope())
using (var scope = _serviceProvider.CreateScope()) {
{
var provider = scope.ServiceProvider; var provider = scope.ServiceProvider;
var serviceType = context.ConsumerDescriptor.ImplTypeInfo.AsType(); var srvType = context.ConsumerDescriptor.ServiceTypeInfo?.AsType();
object obj = null; var implType = context.ConsumerDescriptor.ImplTypeInfo.AsType();
if (context.ConsumerDescriptor.ServiceTypeInfo != null) object obj = null;
if (srvType != null)
{ {
obj = provider.GetServices(context.ConsumerDescriptor.ServiceTypeInfo.AsType()) obj = provider.GetServices(srvType).FirstOrDefault(o => o.GetType() == implType);
.FirstOrDefault(o => o.GetType() == serviceType); }
}
if (obj == null) if (obj == null)
{ {
obj = ActivatorUtilities.GetServiceOrCreateInstance(provider, serviceType); obj = ActivatorUtilities.GetServiceOrCreateInstance(provider, implType);
} }
var jsonContent = context.DeliverMessage.Content; var jsonContent = context.DeliverMessage.Content;
var message = _messagePacker.UnPack(jsonContent); var message = _messagePacker.UnPack(jsonContent);
object resultObj; object resultObj;
if (executor.MethodParameters.Length > 0) if (executor.MethodParameters.Length > 0)
{ {
resultObj = await ExecuteWithParameterAsync(executor, obj, message.Content); resultObj = await ExecuteWithParameterAsync(executor, obj, message.Content);
} }
else else
{ {
resultObj = await ExecuteAsync(executor, obj); resultObj = await ExecuteAsync(executor, obj);
} }
return new ConsumerExecutedResult(resultObj, message.Id, message.CallbackName); return new ConsumerExecutedResult(resultObj, message.Id, message.CallbackName);
} }
} }
private async Task<object> ExecuteAsync(ObjectMethodExecutor executor, object @class) private async Task<object> ExecuteAsync(ObjectMethodExecutor executor, object @class)
{ {
if (executor.IsMethodAsync) if (executor.IsMethodAsync)
{ {
return await executor.ExecuteAsync(@class); return await executor.ExecuteAsync(@class);
} }
return executor.Execute(@class); return executor.Execute(@class);
} }
private async Task<object> ExecuteWithParameterAsync(ObjectMethodExecutor executor, private async Task<object> ExecuteWithParameterAsync(ObjectMethodExecutor executor,
object @class, string parameterString) object @class, string parameterString)
{ {
var firstParameter = executor.MethodParameters[0]; var firstParameter = executor.MethodParameters[0];
try try
{ {
var binder = _modelBinderFactory.CreateBinder(firstParameter); var binder = _modelBinderFactory.CreateBinder(firstParameter);
var bindResult = await binder.BindModelAsync(parameterString); var bindResult = await binder.BindModelAsync(parameterString);
if (bindResult.IsSuccess) if (bindResult.IsSuccess)
{ {
if (executor.IsMethodAsync) if (executor.IsMethodAsync)
{ {
return await executor.ExecuteAsync(@class, bindResult.Model); return await executor.ExecuteAsync(@class, bindResult.Model);
} }
return executor.Execute(@class, bindResult.Model); return executor.Execute(@class, bindResult.Model);
} }
throw new MethodBindException( throw new MethodBindException(
$"Parameters:{firstParameter.Name} bind failed! ParameterString is: {parameterString} "); $"Parameters:{firstParameter.Name} bind failed! ParameterString is: {parameterString} ");
} }
catch (FormatException ex) catch (FormatException ex)
{ {
_logger.ModelBinderFormattingException(executor.MethodInfo?.Name, firstParameter.Name, parameterString, _logger.ModelBinderFormattingException(executor.MethodInfo?.Name, firstParameter.Name, parameterString,
ex); ex);
return null; return null;
} }
} }
} }
} }
\ No newline at end of file
using System;
using System.Reflection;
using System.Threading.Tasks;
using DotNetCore.CAP.Abstractions;
using DotNetCore.CAP.Infrastructure;
using DotNetCore.CAP.Models;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Moq;
using Xunit;
namespace DotNetCore.CAP.Test
{
public class ConsumerInvokerTest
{
private ILoggerFactory _loggerFactory;
private Mock<IMessagePacker> _mockMessagePacker;
private Mock<IModelBinderFactory> _mockModelBinderFactory;
private MessageContext _messageContext;
public ConsumerInvokerTest()
{
_loggerFactory = new NullLoggerFactory();
_mockMessagePacker = new Mock<IMessagePacker>();
_mockModelBinderFactory = new Mock<IModelBinderFactory>();
}
private Internal.DefaultConsumerInvoker InitDefaultConsumerInvoker(IServiceProvider provider)
{
var invoker = new Internal.DefaultConsumerInvoker(
_loggerFactory,
provider,
_mockMessagePacker.Object,
_mockModelBinderFactory.Object);
var message = new CapReceivedMessage
{
Id = SnowflakeId.Default().NextId(),
Name = "test",
Content = DateTime.Now.ToString(),
StatusName = StatusName.Scheduled,
Group = "Group.Test"
};
_mockMessagePacker
.Setup(x => x.UnPack(It.IsAny<string>()))
.Returns(new CapMessageDto(message.Content));
_messageContext = new MessageContext
{
Group = message.Group,
Name = message.Name,
Content = Helper.ToJson(message)
};
return invoker;
}
[Fact]
public async Task CanInvokeServiceTest()
{
var services = new ServiceCollection();
services.AddSingleton<ITestService, TestService2>();
services.AddSingleton<ITestService, TestService>();
var provider = services.BuildServiceProvider();
var invoker = InitDefaultConsumerInvoker(provider);
var descriptor = new ConsumerExecutorDescriptor
{
ServiceTypeInfo = typeof(ITestService).GetTypeInfo(),
ImplTypeInfo = typeof(TestService).GetTypeInfo(),
MethodInfo = typeof(TestService).GetMethod("Index")
};
descriptor.Attribute = descriptor.MethodInfo.GetCustomAttribute<TopicAttribute>(true);
var context = new Internal.ConsumerContext(descriptor, _messageContext);
var result = await invoker.InvokeAsync(context);
Assert.NotNull(result);
Assert.NotNull(result.Result);
Assert.Equal("test", result.Result.ToString());
}
[Fact]
public async Task CanInvokeControllerTest()
{
var services = new ServiceCollection();
var provider = services.BuildServiceProvider();
var invoker = InitDefaultConsumerInvoker(provider);
var descriptor = new ConsumerExecutorDescriptor
{
ServiceTypeInfo = typeof(HomeController).GetTypeInfo(),
ImplTypeInfo = typeof(HomeController).GetTypeInfo(),
MethodInfo = typeof(HomeController).GetMethod("Index")
};
descriptor.Attribute = descriptor.MethodInfo.GetCustomAttribute<TopicAttribute>(true);
var context = new Internal.ConsumerContext(descriptor, _messageContext);
var result = await invoker.InvokeAsync(context);
Assert.NotNull(result);
Assert.NotNull(result.Result);
Assert.Equal("test", result.Result.ToString());
}
}
public class HomeController
{
[CapSubscribe("test")]
public string Index()
{
return "test";
}
}
public interface ITestService { }
public class TestService : ITestService, ICapSubscribe
{
[CapSubscribe("test")]
public string Index()
{
return "test";
}
}
public class TestService2 : ITestService
{
[CapSubscribe("test")]
public string Index()
{
return "test2";
}
}
public class CapSubscribeAttribute : TopicAttribute
{
public CapSubscribeAttribute(string name) : base(name)
{
}
}
}
\ No newline at end of file
using System;
using DotNetCore.CAP.Abstractions;
using Microsoft.Extensions.DependencyInjection;
using Xunit;
namespace DotNetCore.CAP.Test
{
public class SubscribeFinderTest
{
private IServiceProvider _provider;
public SubscribeFinderTest()
{
var services = new ServiceCollection();
services.AddScoped<ITestService, TestService>();
services.AddCap(x => { });
_provider = services.BuildServiceProvider();
}
[Fact]
public void CanFindControllers()
{
}
[Fact]
public void CanFindSubscribeService()
{
var testService = _provider.GetService<ICapSubscribe>();
Assert.NotNull(testService);
Assert.IsType<TestService>(testService);
}
}
public class HomeController
{
}
public interface ITestService { }
public class TestService : ITestService, ICapSubscribe
{
[CapSubscribe("test")]
public void Index()
{
}
}
public class CapSubscribeAttribute : TopicAttribute
{
public CapSubscribeAttribute(string name) : base(name)
{
}
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment