示例#1
0
        public async Task NotifyOfOrderFailureAsyncReturnsTheExceptionResultIfCreatingTheMessageThrows()
        {
            var config = new EmailNotifierConfiguration {
                Enabled = true
            };
            var mockLogger = new Mock <ILogger>();
            var notifier   = new Mock <UnderTest.EmailNotifier>(config, mockLogger.Object)
            {
                CallBase = true
            };

            mockLogger
            .Setup(logger => logger.ForContext(It.IsAny <string>(), It.IsAny <object>(), It.IsAny <bool>()))
            .Returns(mockLogger.Object);

            notifier
            .Protected()
            .Setup <MailMessage>("CreateMessage", ItExpr.IsAny <string>(), ItExpr.IsAny <string>(), ItExpr.IsAny <string>(), ItExpr.IsAny <IEnumerable <string> >())
            .Throws(new MissingDependencyException());

            var result = await notifier.Object.NotifyOfOrderFailureAsync("ABC", "123");

            result.Should().NotBeNull("becuase a result should have been returned");
            result.ShouldBeEquivalentTo(OperationResult.ExceptionResult, "because the exception should short-circuit the processing");
        }
示例#2
0
        public async Task NotifyDeadLetterMessageAsyncRespectsTheEnabledFlag()
        {
            var config = new EmailNotifierConfiguration {
                Enabled = false
            };
            var mockLogger = new Mock <ILogger>();
            var notifier   = new Mock <UnderTest.EmailNotifier>(config, mockLogger.Object)
            {
                CallBase = true
            };

            mockLogger
            .Setup(logger => logger.ForContext(It.IsAny <string>(), It.IsAny <object>(), It.IsAny <bool>()))
            .Returns(mockLogger.Object);

            var result = await notifier.Object.NotifyDeadLetterMessageAsync("Some-Queue", "ABC", "123");

            notifier
            .Protected()
            .Verify("CreateMessage", Times.Never(), ItExpr.IsAny <string>(), ItExpr.IsAny <string>(), ItExpr.IsAny <string>(), ItExpr.IsAny <IEnumerable <string> >());

            notifier
            .Protected()
            .Verify("CreateSmtpClient", Times.Never(), ItExpr.IsAny <EmailNotifierConfiguration>());

            notifier
            .Protected()
            .Verify("SendMessage", Times.Never(), ItExpr.IsAny <SmtpClient>(), ItExpr.IsAny <MailMessage>());

            result.Should().NotBeNull("becuase a result should have been returned");
            result.Outcome.Should().Be(Outcome.Success, "because a skipped notification should be successful");
        }
示例#3
0
        public async Task NotifyDeadLetterMessageAsyncBuildsTheCorrectMessage()
        {
            var config = new EmailNotifierConfiguration
            {
                Enabled = true,
                DeadLetterNotificationBody    = "{location}/{partner}/{orderId}/{correlationId}",
                DeadLetterNotificationSubject = "omg! subject",
                FromEmailAddress   = "*****@*****.**",
                ToEmailAddressList = "[email protected],[email protected]"
            };

            var mockLogger = new Mock <ILogger>();
            var notifier   = new Mock <UnderTest.EmailNotifier>(config, mockLogger.Object)
            {
                CallBase = true
            };
            var client      = new SmtpClient();
            var message     = default(MailMessage);
            var location    = "process-order";
            var partner     = "ABC";
            var order       = "345";
            var correlation = "DEF456";

            var expectedBody = config.DeadLetterNotificationBody
                               .Replace("{location}", location)
                               .Replace("{partner}", partner)
                               .Replace("{orderId}", order)
                               .Replace("{correlationId}", correlation);

            mockLogger
            .Setup(logger => logger.ForContext(It.IsAny <string>(), It.IsAny <object>(), It.IsAny <bool>()))
            .Returns(mockLogger.Object);

            notifier
            .Protected()
            .Setup <SmtpClient>("CreateSmtpClient", ItExpr.IsAny <EmailNotifierConfiguration>())
            .Returns(client);

            notifier
            .Protected()
            .Setup("SendMessage", ItExpr.Is <SmtpClient>(value => value == client), ItExpr.IsAny <MailMessage>())
            .Callback <SmtpClient, MailMessage>((clientParam, messageParam) => message = messageParam);

            var result = await notifier.Object.NotifyDeadLetterMessageAsync(location, partner, order, correlation);

            result.Should().NotBeNull("becuase a result should have been returned");
            result.Outcome.Should().Be(Outcome.Success, "because the notification should be successful");

            message.Should().NotBeNull("because the message should have been sent");
            message.Subject.Should().Be(config.DeadLetterNotificationSubject, "because the configuration subject should be used");
            message.Body.Should().Be(expectedBody, "because the body should have been populated from the configuration and parameers");
            message.From.Should().Be(config.FromEmailAddress);

            foreach (var recipient in config.ToEmailAddressList.Split(','))
            {
                message.To.Any(to => to.Address == recipient).Should().BeTrue("because the recipient {0} should be on the message", recipient);
            }
        }
示例#4
0
        /// <summary>
        ///   Initializes a new instance of the <see cref="EmailNotifier"/> class.
        /// </summary>
        ///
        /// <param name="configuration">The configuration to use for influencing behavior of the notifier.</param>
        /// <param name="logger">The logger to be used for emitting telemetry from the controller.</param>
        /// <param name="jsonSerializerSettings">The settings to use for JSON serializerion.</param>
        ///
        public EmailNotifier(EmailNotifierConfiguration configuration,
                             ILogger logger)
        {
            this.configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
            this.Log           = logger ?? throw new ArgumentNullException(nameof(logger));

            this.emailToAddresses = this.SplitEmailAddressList(EmailNotifier.EmailAddressListSplitChars, configuration.ToEmailAddressList);
            this.rng = new Random();
        }
示例#5
0
 /// <summary>
 ///   Performs the actions needed to create an SMTP client that can be used to
 ///   sent email.
 /// </summary>
 ///
 /// <param name="configuration">The configuration to use for configuring the SMTP client.</param>
 ///
 /// <returns>The SMTP client with the requested configuration</returns>
 ///
 protected virtual SmtpClient CreateSmtpClient(EmailNotifierConfiguration configuration) =>
 new SmtpClient
 {
     Host                  = configuration.SmtpHostAddress,
     Port                  = configuration.SmtpPort,
     DeliveryMethod        = SmtpDeliveryMethod.Network,
     UseDefaultCredentials = false,
     Credentials           = new NetworkCredential(configuration.SmtpUserName, configuration.SmtpPasword),
     Timeout               = configuration.SmtpTimeoutMilliseconds
 };
示例#6
0
        public async Task NotifyDeadLetterMessageAsyncBuildsTheCorrectClient()
        {
            var config = new EmailNotifierConfiguration
            {
                Enabled                 = true,
                SmtpHostAddress         = "server.thing.com",
                SmtpPort                = 1234,
                SmtpUserName            = "******",
                SmtpPasword             = "fly",
                SmtpTimeoutMilliseconds = 4
            };

            var mockLogger = new Mock <ILogger>();
            var notifier   = new Mock <UnderTest.EmailNotifier>(config, mockLogger.Object)
            {
                CallBase = true
            };
            var client      = default(SmtpClient);
            var message     = new MailMessage();
            var location    = "process-order";
            var partner     = "ABC";
            var order       = "345";
            var correlation = "DEF456";

            mockLogger
            .Setup(logger => logger.ForContext(It.IsAny <string>(), It.IsAny <object>(), It.IsAny <bool>()))
            .Returns(mockLogger.Object);

            notifier
            .Protected()
            .Setup <MailMessage>("CreateMessage", ItExpr.IsAny <string>(), ItExpr.IsAny <string>(), ItExpr.IsAny <string>(), ItExpr.IsAny <IEnumerable <string> >())
            .Returns(message);

            notifier
            .Protected()
            .Setup("SendMessage", ItExpr.IsAny <SmtpClient>(), ItExpr.Is <MailMessage>(value => value == message))
            .Callback <SmtpClient, MailMessage>((clientParam, messageParam) => client = clientParam);

            var result = await notifier.Object.NotifyDeadLetterMessageAsync(location, partner, order, correlation);

            result.Should().NotBeNull("becuase a result should have been returned");
            result.Outcome.Should().Be(Outcome.Success, "because the notification should be successful");

            client.Should().NotBeNull("because the message should have been sent using the client");
            client.Host.Should().Be(config.SmtpHostAddress, "because the host from configuration should be used");
            client.Port.Should().Be(config.SmtpPort, "because the port from configuration should be used");
            client.Timeout.Should().Be(config.SmtpTimeoutMilliseconds, "because the timeout from configuration should be used");

            var credentials = client.Credentials as NetworkCredential;

            credentials.Should().NotBeNull("because the credentials should be set");
            credentials.UserName.Should().Be(config.SmtpUserName, "because the user from configuration should have been used");
            credentials.Password.Should().Be(config.SmtpPasword, "because the password from configuration should have been used");
        }
示例#7
0
        public async Task NotifyDeadLetterMessageAsyncSendsTheEmailNotification()
        {
            var config = new EmailNotifierConfiguration {
                Enabled = true
            };
            var mockLogger = new Mock <ILogger>();
            var notifier   = new Mock <UnderTest.EmailNotifier>(config, mockLogger.Object)
            {
                CallBase = true
            };
            var message = new MailMessage();
            var client  = new SmtpClient();

            mockLogger
            .Setup(logger => logger.ForContext(It.IsAny <string>(), It.IsAny <object>(), It.IsAny <bool>()))
            .Returns(mockLogger.Object);

            notifier
            .Protected()
            .Setup <MailMessage>("CreateMessage", ItExpr.IsAny <string>(), ItExpr.IsAny <string>(), ItExpr.IsAny <string>(), ItExpr.IsAny <IEnumerable <string> >())
            .Returns(message);

            notifier
            .Protected()
            .Setup <SmtpClient>("CreateSmtpClient", ItExpr.IsAny <EmailNotifierConfiguration>())
            .Returns(client);

            notifier
            .Protected()
            .Setup("SendMessage", ItExpr.Is <SmtpClient>(value => value == client), ItExpr.Is <MailMessage>(value => value == message))
            .Verifiable("The message should have been sent");

            var result = await notifier.Object.NotifyDeadLetterMessageAsync("Some-Queue", "ABC", "123");

            result.Should().NotBeNull("becuase a result should have been returned");
            result.Outcome.Should().Be(Outcome.Success, "because the notification should be successful");

            notifier.VerifyAll();
        }
示例#8
0
        public async Task NotifyDeadLetterMessageAsyncHonorsTheRetryPolicyIfSendingTheMessageThrows()
        {
            var config = new EmailNotifierConfiguration {
                Enabled = true, OperationRetryMaxCount = 4, OperationRetryExponentialSeconds = 0, OperationRetryJitterSeconds = 0
            };
            var mockLogger = new Mock <ILogger>();
            var notifier   = new Mock <UnderTest.EmailNotifier>(config, mockLogger.Object)
            {
                CallBase = true
            };
            var retries = 0;

            mockLogger
            .Setup(logger => logger.ForContext(It.IsAny <string>(), It.IsAny <object>(), It.IsAny <bool>()))
            .Returns(mockLogger.Object);

            notifier
            .Protected()
            .Setup <MailMessage>("CreateMessage", ItExpr.IsAny <string>(), ItExpr.IsAny <string>(), ItExpr.IsAny <string>(), ItExpr.IsAny <IEnumerable <string> >())
            .Returns(new MailMessage());

            notifier
            .Protected()
            .Setup <SmtpClient>("CreateSmtpClient", ItExpr.IsAny <EmailNotifierConfiguration>())
            .Returns(new SmtpClient());

            notifier
            .Protected()
            .Setup("SendMessage", ItExpr.IsAny <SmtpClient>(), ItExpr.IsAny <MailMessage>())
            .Callback(() => ++ retries)
            .Throws(new NullReferenceException());

            var result = await notifier.Object.NotifyDeadLetterMessageAsync("Process", "ABC", "123");

            retries.Should().Be(config.OperationRetryMaxCount + 1, "because a failure should trigger the retry policy");
        }