private static async Task ReceiveMessageAsync(Options options)
        {
            var consumer = GetSchemaConsumer(options);

            var validator = new SchemaValidator()
                            .WithSchemaConsumer(consumer);

            var plugin = new SchemaValidatorPlugin()
                         .WithValidator(validator);

            var subscription = new SubscriptionClient(options.ServiceBusConnectionString, options.Topic, options.Subscription, ReceiveMode.PeekLock);

            subscription.RegisterPlugin(plugin);
            subscription.RegisterMessageHandler(async(message, token) =>
            {
                Console.WriteLine($"MessageId: {message.MessageId}, SequenceNumber: {message.SystemProperties.SequenceNumber}");

                var payload = Encoding.UTF8.GetString(message.Body);

                Console.WriteLine(payload);

                await subscription.CompleteAsync(message.SystemProperties.LockToken)
                .ConfigureAwait(false);

                Console.WriteLine(MessageReceived);
            },
                                                new MessageHandlerOptions(OnExceptionReceived));

            await Task.CompletedTask
            .ConfigureAwait(false);
        }
        private static async Task SendMessageAsync <T>(Options options, T payload)
        {
            var consumer = GetSchemaConsumer(options);

            var validator = new SchemaValidator()
                            .WithSchemaConsumer(consumer);

            var plugin = new SchemaValidatorPlugin()
                         .WithValidator(validator);

            var topic = new TopicClient(options.ServiceBusConnectionString, options.Topic);

            topic.RegisterPlugin(plugin);

            var serialised = JsonConvert.SerializeObject(payload, Settings.SerializerSettings);
            var body       = Encoding.UTF8.GetBytes(serialised);
            var message    = new Message(body);

            message.UserProperties.Add("schemaPath", $"{options.BlobBaseUri.TrimEnd('/')}/{options.Container.Trim('/')}/{options.Filepath.TrimStart('/')}");

            await topic.SendAsync(message)
            .ConfigureAwait(false);

            Console.WriteLine(MessageSent);
        }
        public void Given_Null_Message_When_AfterMessageReceive_Invoked_Then_It_Should_Throw_Exception()
        {
            var instance = new SchemaValidatorPlugin();

            Func <Task> func = async() => await instance.AfterMessageReceive(null).ConfigureAwait(false);

            func.Should().Throw <ArgumentNullException>();
        }
        public void Given_SchemaPathUserPropertyKey_When_WithValidator_Invoked_Then_It_Should_Return_Result(string schemaPathUserPropertyKey)
        {
            var instance = new SchemaValidatorPlugin();

            var result = instance.WithSchemaPathUserPropertyKey(schemaPathUserPropertyKey);

            result.As <ISchemaValidatorPlugin>().SchemaPathUserPropertyKey.Should().Be(schemaPathUserPropertyKey);
        }
        public void Given_Null_SchemaPathUserPropertyKey_When_WithValidator_Invoked_Then_It_Should_Throw_Exception()
        {
            var instance = new SchemaValidatorPlugin();

            Action action = () => instance.WithSchemaPathUserPropertyKey(null);

            action.Should().Throw <ArgumentNullException>();
        }
        public void Given_Default_When_Instantiated_Then_It_Should_Return_Default_Properties()
        {
            var instance = new SchemaValidatorPlugin();

            instance.Name.Should().Be(typeof(SchemaValidatorPlugin).FullName);
            instance.ShouldContinueOnException.Should().BeFalse();
            instance.Validator.Should().BeNull();
            instance.SchemaPathUserPropertyKey.Should().Be("schemaPath");
        }
        public void Given_Validator_When_WithValidator_Invoked_Then_It_Should_Return_Result()
        {
            var validator = new FakeSchemaValidator();
            var instance  = new SchemaValidatorPlugin();

            var result = instance.WithValidator(validator);

            result.As <ISchemaValidatorPlugin>().Validator.Should().Be(validator);
        }
        public void Given_Parameters_When_Instantiated_Then_It_Should_Return_Value(string schemaPathUserPropertyKey, bool shouldContinueOnException)
        {
            var instance = new SchemaValidatorPlugin(schemaPathUserPropertyKey, shouldContinueOnException);

            instance.Name.Should().Be(typeof(SchemaValidatorPlugin).FullName);
            instance.ShouldContinueOnException.Should().Be(shouldContinueOnException);
            instance.Validator.Should().BeNull();
            instance.SchemaPathUserPropertyKey.Should().Be(schemaPathUserPropertyKey);
        }
        public void Given_Message_Without_SchemaPath_When_AfterMessageReceive_Invoked_Then_It_Should_Throw_Exception(string body)
        {
            var bytes    = Encoding.UTF8.GetBytes(body);
            var message  = new Message(bytes);
            var instance = new SchemaValidatorPlugin();

            Func <Task> func = async() => await instance.AfterMessageReceive(message).ConfigureAwait(false);

            func.Should().Throw <KeyNotFoundException>();
        }
        public void Given_Empty_Message_When_AfterMessageReceive_Invoked_Then_It_Should_Throw_Exception()
        {
            var body     = Array.Empty <byte>();
            var message  = new Message(body);
            var instance = new SchemaValidatorPlugin();

            Func <Task> func = async() => await instance.AfterMessageReceive(message).ConfigureAwait(false);

            func.Should().Throw <MessageBodyZeroLengthException>();
        }
        public void Given_Message_With_Empty_SchemaPath_When_AfterMessageReceive_Invoked_Then_It_Should_Throw_Exception(string body)
        {
            var bytes   = Encoding.UTF8.GetBytes(body);
            var message = new Message(bytes);

            message.UserProperties.Add("schemaPath", string.Empty);

            var instance = new SchemaValidatorPlugin();

            Func <Task> func = async() => await instance.AfterMessageReceive(message).ConfigureAwait(false);

            func.Should().Throw <SchemaPathNotExistException>();
        }
        public async Task Given_Message_When_AfterMessageReceive_Invoked_Then_It_Should_Return_Result(string body, string path)
        {
            var validator = new Mock <ISchemaValidator>();

            validator.Setup(p => p.ValidateAsync(It.IsAny <string>(), It.IsAny <string>())).ReturnsAsync(true);

            var bytes   = Encoding.UTF8.GetBytes(body);
            var message = new Message(bytes);

            message.UserProperties.Add("schemaPath", path);

            var instance = new SchemaValidatorPlugin()
                           .WithValidator(validator.Object);

            var result = await instance.AfterMessageReceive(message).ConfigureAwait(false);

            result.Should().Be(message);
        }
        public void Given_Validation_Error_When_AfterMessageReceive_Invoked_Then_It_Should_Throw_Exception(string body, string path)
        {
            var exception = new SchemaValidationException();
            var validator = new Mock <ISchemaValidator>();

            validator.Setup(p => p.ValidateAsync(It.IsAny <string>(), It.IsAny <string>())).ThrowsAsync(exception);

            var bytes   = Encoding.UTF8.GetBytes(body);
            var message = new Message(bytes);

            message.UserProperties.Add("schemaPath", path);

            var instance = new SchemaValidatorPlugin()
                           .WithValidator(validator.Object);

            Func <Task> func = async() => await instance.AfterMessageReceive(message).ConfigureAwait(false);

            func.Should().Throw <SchemaValidationException>();
        }