예제 #1
0
        /// <summary>
        ///     Execute query
        /// </summary>
        /// <typeparam name="TResult">Query result type</typeparam>
        /// <param name="query">Query to execute</param>
        /// <returns>result</returns>
        /// <exception cref="ArgumentNullException">query</exception>
        /// <exception cref="OnlyOneQueryHandlerAllowedException">If multiple handlers have been registered for the query</exception>
        /// <exception cref="NoHandlerRegisteredException">A handler have not been registered for the given query</exception>
        public async Task <TResult> QueryAsync <TResult>(Query <TResult> query)
        {
            if (query == null)
            {
                throw new ArgumentNullException(nameof(query));
            }
            var ctx = new ExecuteQueriesInvocationContext(null, _messageInvoker);

            return(await ctx.QueryAsync(query));
        }
예제 #2
0
        public void Should_require_a_query_handler()
        {
            var scope  = Substitute.For <IHandlerScope>();
            var result = new OneResult();

            scope.Create(typeof(IQueryHandler <OneQuery, OneResult>)).Returns(new object[0]);

            var         sut     = new MessageInvoker(scope);
            var         context = new ExecuteQueriesInvocationContext(ClaimsPrincipal.Current, sut);
            Func <Task> actual  = () => sut.ProcessAsync(context, new OneQuery());

            actual.Should().Throw <NoHandlerRegisteredException>();
        }
예제 #3
0
        Should_be_able_to_reply_with_null_since_that_indicates_that_the_requested_resource_is_not_found()
        {
            var scope        = Substitute.For <IHandlerScope>();
            var handler      = new MyHandler();
            var msg          = new Message(new MyQuery());
            var sut          = new MessageInvoker(scope);
            var queryContext = new ExecuteQueriesInvocationContext(new ClaimsPrincipal(), sut);

            scope.Create(typeof(IQueryHandler <MyQuery, string>)).Returns(new object[] { handler });

            await sut.ProcessAsync(queryContext, msg);

            queryContext.Replies.Should().NotBeEmpty();
        }
예제 #4
0
        public async Task Should_be_able_to_execute_query_sucessfully()
        {
            var scope   = Substitute.For <IHandlerScope>();
            var result  = new OneResult();
            var handler = new OneQueryHandler(result);

            scope.Create(typeof(IQueryHandler <OneQuery, OneResult>)).Returns(new[] { handler });

            var sut     = new MessageInvoker(scope);
            var context = new ExecuteQueriesInvocationContext(ClaimsPrincipal.Current, sut);
            await sut.ProcessAsync(context, new OneQuery());

            context.Replies.First().Body.Should().BeSameAs(result);
        }
예제 #5
0
        public async Task Should_invoke_message_handler()
        {
            var scope   = Substitute.For <IHandlerScope>();
            var handler = new TestHandler <Simple>();

            scope.Create(typeof(IMessageHandler <Simple>)).Returns(new[] { handler });
            var msg     = new Message(new Simple());
            var sut     = new MessageInvoker(scope);
            var context = new ExecuteQueriesInvocationContext(ClaimsPrincipal.Current, sut);

            await sut.ProcessAsync(context, msg);

            handler.Invoked.Should().BeTrue();
        }
예제 #6
0
        public void Should_abort_if_multiple_query_handlers_have_been_registered()
        {
            var scope   = Substitute.For <IHandlerScope>();
            var result  = new OneResult();
            var handler = new OneQueryHandler(result);

            scope.Create(typeof(IQueryHandler <OneQuery, OneResult>)).Returns(new[] { handler, handler });

            var         sut     = new MessageInvoker(scope);
            var         context = new ExecuteQueriesInvocationContext(ClaimsPrincipal.Current, sut);
            Func <Task> actual  = () => sut.ProcessAsync(context, new OneQuery());

            actual.Should().Throw <OnlyOneQueryHandlerAllowedException>();
        }
예제 #7
0
        public async Task Should_be_able_to_reply_with_a_message()
        {
            var scope   = Substitute.For <IHandlerScope>();
            var handler = new MyHandler {
                Result = "Word!"
            };
            var msg          = new Message(new MyQuery());
            var sut          = new MessageInvoker(scope);
            var queryContext = new ExecuteQueriesInvocationContext(new ClaimsPrincipal(), sut);

            scope.Create(typeof(IQueryHandler <MyQuery, string>)).Returns(new object[] { handler });

            await sut.ProcessAsync(queryContext, msg);

            queryContext.Replies[0].Body.Should().Be("Word!");
        }
예제 #8
0
        public void Should_report_all_failed_handlers_in_the_exception()
        {
            var scope    = Substitute.For <IHandlerScope>();
            var handler  = new TestHandler <Simple>((ctx, msg2) => throw new InvalidOperationException("No Data :("));
            var handler2 = new TestHandler <Simple>((ctx, msg2) => throw new DataException("Here comes Lore!"));

            scope.Create(typeof(IMessageHandler <Simple>)).Returns(new[] { handler, handler2 });
            var msg     = new Message(new Simple());
            var sut     = new MessageInvoker(scope);
            var context = new ExecuteQueriesInvocationContext(ClaimsPrincipal.Current, sut);

            Func <Task> actual = () => sut.ProcessAsync(context, msg);

            actual.Should().Throw <HandlersFailedException>()
            .And.FailedHandlers.Count.Should().Be(2);
        }
예제 #9
0
        public void Should_let_exceptions_flow_to_allow_caller_to_decide_appropiate_response()
        {
            var scope    = Substitute.For <IHandlerScope>();
            var handler  = new TestHandler <Simple>();
            var handler2 = new TestHandler <Simple>((ctx, msg2) => throw new DataException("Here comes Lore!"));

            scope.Create(typeof(IMessageHandler <Simple>)).Returns(new[] { handler, handler2 });
            var msg     = new Message(new Simple());
            var sut     = new MessageInvoker(scope);
            var context = new ExecuteQueriesInvocationContext(ClaimsPrincipal.Current, sut);

            Func <Task> actual = () => sut.ProcessAsync(context, msg);

            actual.Should().Throw <HandlersFailedException>()
            .And.FailedHandlers[0].Exception.Message.Should().Be("Here comes Lore!");
        }
예제 #10
0
        public async Task Should_invoke_second_level_queries_directly()
        {
            var            scope    = Substitute.For <IHandlerScope>();
            var            result   = new OneResult();
            QueryTwoResult expected = null;
            var            handler  = new OneQueryHandler(result, (messageContext, query) =>
            {
                expected = messageContext.QueryAsync(new QueryTwo()).GetAwaiter().GetResult();
            });
            var result2  = new QueryTwoResult();
            var handler2 = new QueryTwoHandler(result2);

            scope.Create(typeof(IQueryHandler <OneQuery, OneResult>)).Returns(new[] { handler });
            scope.Create(typeof(IQueryHandler <QueryTwo, QueryTwoResult>)).Returns(new[] { handler2 });

            var sut     = new MessageInvoker(scope);
            var context = new ExecuteQueriesInvocationContext(ClaimsPrincipal.Current, sut);
            await sut.ProcessAsync(context, new OneQuery());

            expected.Should().BeSameAs(result2, "because it should not be enqueued as queries that comes from the queue");
            context.Replies.Count.Should().Be(1, "because only result from first queue should be enqueued");
            context.Replies.First().Body.Should().Be(result);
            context.Messages.Should().BeEmpty("because no messages were enqueued by the handlers");
        }
        public async Task <TResult> QueryAsync <TResult>(Query <TResult> query)
        {
            var ctx = new ExecuteQueriesInvocationContext(Principal, _messageInvoker);

            return(await ctx.QueryAsync(query));
        }