Skip to content

Commit

Permalink
Integration-test
Browse files Browse the repository at this point in the history
  • Loading branch information
tba76 committed Sep 7, 2023
1 parent 22414b4 commit 08c6712
Show file tree
Hide file tree
Showing 12 changed files with 131 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public enum EmailNotificationResultType
Sending,

/// <summary>
/// Email notification sent and delivered
/// Email notification sent
/// </summary>
Succeeded,

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Text.Json;
using System.Text.Json.Serialization;
using Altinn.Notifications.Core.Enums;
using Altinn.Notifications.Core.Models.Orders;

namespace Altinn.Notifications.Core.Models.Notification;

Expand All @@ -24,6 +25,21 @@ public class SendOperationResult
/// </summary>
public EmailNotificationResultType? SendResult { get; set; }

/// <summary>
/// Json serializes the <see cref="SendOperationResult"/>
/// </summary>
public string Serialize()
{
return JsonSerializer.Serialize(
this,
new JsonSerializerOptions
{
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
Converters = { new JsonStringEnumConverter() }
});
}

/// <summary>
/// Deserialize a json string into the <see cref="SendOperationResult"/>
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ public interface IEmailNotificationRepository
public Task<List<Email>> GetNewNotifications();

/// <summary>
/// Sets result status of an email notification
/// Sets result status of an email notification and update operation id
/// </summary>
public Task SetResultStatus(Guid notificationId, EmailNotificationResultType status);
public Task SetResultStatus(Guid notificationId, EmailNotificationResultType status, string? operationId);

/// <summary>
/// Retrieves all email recipients for an order
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,15 @@ public async Task SendNotifications()
bool success = await _producer.ProduceAsync(_emailQueueTopicName, email.Serialize());
if (!success)
{
await _repository.SetResultStatus(email.NotificationId, EmailNotificationResultType.New);
await _repository.SetResultStatus(email.NotificationId, EmailNotificationResultType.New, null);
}
}
}

/// <inheritdoc/>
public async Task UpdateStatusNotification(SendOperationResult sendOperationResult)
public async Task UpdateSendStatus(SendOperationResult sendOperationResult)
{
await _repository.SetResultStatus(sendOperationResult.NotificationId, (EmailNotificationResultType)sendOperationResult.SendResult!);
await _repository.SetResultStatus(sendOperationResult.NotificationId, (EmailNotificationResultType)sendOperationResult.SendResult!, sendOperationResult.OperationId);
}

private async Task CreateNotificationForRecipient(Guid orderId, DateTime requestedSendTime, string recipientId, string toAddress, EmailNotificationResultType result)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@ public interface IEmailNotificationService
/// <summary>
/// Update send status for a notification
/// </summary>
public Task UpdateStatusNotification(SendOperationResult sendOperationResult);
public Task UpdateSendStatus(SendOperationResult sendOperationResult);
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public static void AddKafkaServices(this IServiceCollection services, IConfigura
.AddSingleton<IKafkaProducer, KafkaProducer>()
.AddHostedService<PastDueOrdersConsumer>()
.AddHostedService<PastDueOrdersRetryConsumer>()
.AddHostedService<EmailStatusConsumer>()
.Configure<KafkaSettings>(config.GetSection(nameof(KafkaSettings)));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ private async Task ProcessOrder(string message)
return;
}

await _emailNotificationsService.UpdateStatusNotification(result);
await _emailNotificationsService.UpdateSendStatus(result);
}

private async Task RetryOrder(string message)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
ALTER TABLE notifications.emailnotifications
ADD COLUMN operationid text;
ADD COLUMN IF NOT EXISTS operationid text;
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,12 @@ public async Task<List<Email>> GetNewNotifications()
}

/// <inheritdoc/>
public async Task SetResultStatus(Guid notificationId, EmailNotificationResultType status)
public async Task SetResultStatus(Guid notificationId, EmailNotificationResultType status, string? operationId)
{
await using NpgsqlCommand pgcom = _dataSource.CreateCommand(_setResultStatus);
pgcom.Parameters.AddWithValue(NpgsqlDbType.Uuid, notificationId);
pgcom.Parameters.AddWithValue(NpgsqlDbType.Text, status.ToString());
pgcom.Parameters.AddWithValue(NpgsqlDbType.Text, operationId ?? (object)DBNull.Value);
await pgcom.ExecuteNonQueryAsync();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
using Altinn.Notifications.Core.Enums;
using Altinn.Notifications.Core.Models.Notification;
using Altinn.Notifications.Core.Models.Orders;
using Altinn.Notifications.Integrations.Kafka.Consumers;
using Altinn.Notifications.IntegrationTests.Utils;

using Microsoft.Extensions.Hosting;

using Xunit;

namespace Altinn.Notifications.IntegrationTests.Notifications.Core.Consumers;

public class EmailStatusConsumerTests : IDisposable
{
private readonly string _statusUpdatedTopicName = Guid.NewGuid().ToString();
private readonly string _sendersRef = $"ref-{Guid.NewGuid()}";

[Fact]
public async Task RunTask_ConfirmExpectedSideEffects()
{
// Arrange
Dictionary<string, string> vars = new()
{
{ "KafkaSettings__EmailStatusUpdatedTopicName", _statusUpdatedTopicName },
{ "KafkaSettings__Admin__TopicList", $"[\"{_statusUpdatedTopicName}\"]" }
};

using EmailStatusConsumer consumerService = (EmailStatusConsumer)ServiceUtil
.GetServices(new List<Type>() { typeof(IHostedService) }, vars)
.First(s => s.GetType() == typeof(EmailStatusConsumer))!;

(NotificationOrder Order, EmailNotification Notification) = await PostgreUtil.PopulateDBWithOrderAndEmailNotification(_sendersRef);

SendOperationResult sendOperationResult = new()
{
NotificationId = Notification.Id,
OperationId = Guid.NewGuid().ToString(),
SendResult = EmailNotificationResultType.Succeeded
};
await KafkaUtil.PublishMessageOnTopic(_statusUpdatedTopicName, sendOperationResult.Serialize());


// Act
await consumerService.StartAsync(CancellationToken.None);
await Task.Delay(10000);
await consumerService.StopAsync(CancellationToken.None);

// Assert

string emailNotificationStatus = await SelectEmailNotificationStatus(Notification.Id);
Assert.Equal(emailNotificationStatus, EmailNotificationResultType.Succeeded.ToString());

}

public async void Dispose()
{
await Dispose(true);

GC.SuppressFinalize(this);
}

protected virtual async Task Dispose(bool disposing)
{
string sql = $"delete from notifications.orders where sendersreference = '{_sendersRef}'";

await PostgreUtil.RunSql(sql);
await KafkaUtil.DeleteTopicAsync(_statusUpdatedTopicName);
}

private async Task<string> SelectEmailNotificationStatus(Guid notificationId)
{
string sql = $"select result from notifications.emailnotifications where alternateid = '{notificationId}'";
return await PostgreUtil.RunSqlReturnStringOutput(sql);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,6 @@ public static async Task RunSql(string query)
NpgsqlDataSource dataSource = (NpgsqlDataSource)ServiceUtil.GetServices(new List<Type>() { typeof(NpgsqlDataSource) })[0]!;

await using NpgsqlCommand pgcom = dataSource.CreateCommand(query);
await pgcom.ExecuteNonQueryAsync();
pgcom.ExecuteNonQuery();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public async Task SendNotifications_ProducerReturnsFalse_RepositoryCalledToUpdat
.ReturnsAsync(new List<Email>() { _email });

repoMock
.Setup(r => r.SetResultStatus(It.IsAny<Guid>(), It.Is<EmailNotificationResultType>(t => t == EmailNotificationResultType.New)));
.Setup(r => r.SetResultStatus(It.IsAny<Guid>(), It.Is<EmailNotificationResultType>(t => t == EmailNotificationResultType.New), It.IsAny<string?>()));

var producerMock = new Mock<IKafkaProducer>();
producerMock.Setup(p => p.ProduceAsync(It.Is<string>(s => s.Equals(_emailQueueTopicName)), It.IsAny<string>()))
Expand Down Expand Up @@ -136,6 +136,32 @@ public async Task CreateEmailNotification_ToAddressDefined_ResultFailedRecipient
repoMock.Verify();
}

[Fact]
public async Task UpdateStatusNotification()
{
// Arrange
Guid notificationid = Guid.NewGuid();
string operationId = Guid.NewGuid().ToString();

SendOperationResult sendOperationResult = new()
{
NotificationId = notificationid,
OperationId = operationId,
SendResult= EmailNotificationResultType.Succeeded
};

var repoMock = new Mock<IEmailNotificationRepository>();
repoMock.Setup(r => r.SetResultStatus(It.Is<Guid>(n => n == notificationid), It.Is<EmailNotificationResultType>(e => e == EmailNotificationResultType.Succeeded), It.Is<string>(s => s.Equals(operationId))));

var service = GetTestService(repo: repoMock.Object);

// Act
await service.UpdateSendStatus(sendOperationResult);
// Assert

repoMock.Verify();
}

private static EmailNotificationService GetTestService(IEmailNotificationRepository? repo = null, IKafkaProducer? producer = null, Guid? guidOutput = null, DateTime? dateTimeOutput = null)
{
var guidService = new Mock<IGuidService>();
Expand Down

0 comments on commit 08c6712

Please sign in to comment.