mirror of
https://github.com/bitwarden/server.git
synced 2024-11-22 12:15:36 +01:00
PM-10600: Unit tests for NotificationsApiPushNotificationService
Also added HttpClientCustomize fixture, that provides IHttpClientFactory, HttpClient and MockedHttpMessageHandler. The latter can be used to mock requests and provide expected responses. Expanded HttpRequestMatcher to be able to respond with content.
This commit is contained in:
parent
91567ed686
commit
be7929c81d
@ -74,11 +74,16 @@ public class HttpRequestMatcher : IHttpRequestMatcher
|
|||||||
/// Note, after specifying a response, you can no longer further specify match criteria.
|
/// Note, after specifying a response, you can no longer further specify match criteria.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="statusCode"></param>
|
/// <param name="statusCode"></param>
|
||||||
|
/// <param name="content"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public MockedHttpResponse RespondWith(HttpStatusCode statusCode)
|
public MockedHttpResponse RespondWith(HttpStatusCode statusCode, HttpContent? content = null)
|
||||||
{
|
{
|
||||||
_responseSpecified = true;
|
_responseSpecified = true;
|
||||||
_mockedResponse = new MockedHttpResponse(statusCode);
|
_mockedResponse = new MockedHttpResponse(statusCode);
|
||||||
|
if (content != null)
|
||||||
|
{
|
||||||
|
_mockedResponse.WithContent(content);
|
||||||
|
}
|
||||||
return _mockedResponse;
|
return _mockedResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
51
test/Core.Test/AutoFixture/HttpClientFixtures.cs
Normal file
51
test/Core.Test/AutoFixture/HttpClientFixtures.cs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#nullable enable
|
||||||
|
using AutoFixture;
|
||||||
|
using AutoFixture.Kernel;
|
||||||
|
using Bit.Test.Common.AutoFixture.Attributes;
|
||||||
|
using Bit.Test.Common.MockedHttpClient;
|
||||||
|
using NSubstitute;
|
||||||
|
|
||||||
|
namespace Bit.Core.Test.AutoFixture;
|
||||||
|
|
||||||
|
public class HttpClientFactoryBuilder : ISpecimenBuilder
|
||||||
|
{
|
||||||
|
private MockedHttpMessageHandler? _mockedHttpMessageHandler;
|
||||||
|
|
||||||
|
public object Create(object request, ISpecimenContext context)
|
||||||
|
{
|
||||||
|
var type = request as Type;
|
||||||
|
if (type == typeof(IHttpClientFactory))
|
||||||
|
{
|
||||||
|
var handler = context.Create<MockedHttpMessageHandler>();
|
||||||
|
var httpClientFactory = Substitute.For<IHttpClientFactory>();
|
||||||
|
httpClientFactory.CreateClient(Arg.Any<string>()).Returns(handler.ToHttpClient());
|
||||||
|
return httpClientFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == typeof(MockedHttpMessageHandler))
|
||||||
|
{
|
||||||
|
return _mockedHttpMessageHandler ??= new MockedHttpMessageHandler();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == typeof(HttpClient))
|
||||||
|
{
|
||||||
|
var handler = context.Create<MockedHttpMessageHandler>();
|
||||||
|
return handler.ToHttpClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new NoSpecimen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class HttpClientCustomizeAttribute : BitCustomizeAttribute
|
||||||
|
{
|
||||||
|
public override ICustomization GetCustomization() => new HttpClientFixtures();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class HttpClientFixtures : ICustomization
|
||||||
|
{
|
||||||
|
public void Customize(IFixture fixture)
|
||||||
|
{
|
||||||
|
fixture.Customizations.Add(new HttpClientFactoryBuilder());
|
||||||
|
}
|
||||||
|
}
|
@ -1,41 +1,82 @@
|
|||||||
using Bit.Core.Services;
|
#nullable enable
|
||||||
using Bit.Core.Settings;
|
using System.Net;
|
||||||
|
using System.Net.Http.Json;
|
||||||
|
using Bit.Core.Context;
|
||||||
|
using Bit.Core.Enums;
|
||||||
|
using Bit.Core.Models;
|
||||||
|
using Bit.Core.NotificationCenter.Entities;
|
||||||
|
using Bit.Core.Services;
|
||||||
|
using Bit.Core.Test.AutoFixture;
|
||||||
|
using Bit.Core.Test.AutoFixture.CurrentContextFixtures;
|
||||||
|
using Bit.Core.Test.NotificationCenter.AutoFixture;
|
||||||
|
using Bit.Test.Common.AutoFixture;
|
||||||
|
using Bit.Test.Common.AutoFixture.Attributes;
|
||||||
|
using Bit.Test.Common.MockedHttpClient;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using NSubstitute;
|
using NSubstitute;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Bit.Core.Test.Services;
|
namespace Bit.Core.Test.Services;
|
||||||
|
|
||||||
|
[SutProviderCustomize]
|
||||||
|
[HttpClientCustomize]
|
||||||
public class NotificationsApiPushNotificationServiceTests
|
public class NotificationsApiPushNotificationServiceTests
|
||||||
{
|
{
|
||||||
private readonly NotificationsApiPushNotificationService _sut;
|
[Theory]
|
||||||
|
[BitAutoData]
|
||||||
private readonly IHttpClientFactory _httpFactory;
|
[NotificationCustomize]
|
||||||
private readonly GlobalSettings _globalSettings;
|
[CurrentContextCustomize]
|
||||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
public async void PushSyncNotificationAsync_Notification_Sent(
|
||||||
private readonly ILogger<NotificationsApiPushNotificationService> _logger;
|
SutProvider<NotificationsApiPushNotificationService> sutProvider, Notification notification,
|
||||||
|
Guid deviceIdentifier, ICurrentContext currentContext, MockedHttpMessageHandler mockedHttpMessageHandler)
|
||||||
public NotificationsApiPushNotificationServiceTests()
|
|
||||||
{
|
{
|
||||||
_httpFactory = Substitute.For<IHttpClientFactory>();
|
var tokenResponse = mockedHttpMessageHandler
|
||||||
_globalSettings = new GlobalSettings();
|
.When(request =>
|
||||||
_httpContextAccessor = Substitute.For<IHttpContextAccessor>();
|
request.Method == HttpMethod.Post && request.RequestUri!.ToString().EndsWith("/connect/token"))
|
||||||
_logger = Substitute.For<ILogger<NotificationsApiPushNotificationService>>();
|
.RespondWith(HttpStatusCode.OK, new StringContent("{\"access_token\":\"token\"}"));
|
||||||
|
var sendResponse = mockedHttpMessageHandler
|
||||||
|
.When(request =>
|
||||||
|
{
|
||||||
|
if (request.Method != HttpMethod.Post || !request.RequestUri!.ToString().EndsWith("/send") ||
|
||||||
|
request.Content is not JsonContent jsonContent || jsonContent.Value == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
_sut = new NotificationsApiPushNotificationService(
|
var pushNotificationData = (PushNotificationData<SyncNotificationPushNotification>)jsonContent.Value;
|
||||||
_httpFactory,
|
return MatchMessage(PushType.SyncNotification, pushNotificationData,
|
||||||
_globalSettings,
|
new SyncNotificationEquals(notification), deviceIdentifier.ToString());
|
||||||
_httpContextAccessor,
|
})
|
||||||
_logger
|
.RespondWith(HttpStatusCode.OK);
|
||||||
);
|
|
||||||
|
currentContext.DeviceIdentifier.Returns(deviceIdentifier.ToString());
|
||||||
|
sutProvider.GetDependency<IHttpContextAccessor>().HttpContext!.RequestServices
|
||||||
|
.GetService(Arg.Any<Type>()).Returns(currentContext);
|
||||||
|
|
||||||
|
await sutProvider.Sut.PushSyncNotificationAsync(notification);
|
||||||
|
|
||||||
|
Assert.Equal(1, tokenResponse.NumberOfResponses);
|
||||||
|
Assert.Equal(1, sendResponse.NumberOfResponses);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove this test when we add actual tests. It only proves that
|
private static bool MatchMessage<T>(PushType pushType, PushNotificationData<T> pushNotificationData,
|
||||||
// we've properly constructed the system under test.
|
IEquatable<T> expectedPayloadEquatable, string contextId)
|
||||||
[Fact(Skip = "Needs additional work")]
|
|
||||||
public void ServiceExists()
|
|
||||||
{
|
{
|
||||||
Assert.NotNull(_sut);
|
return pushNotificationData.Type == pushType &&
|
||||||
|
expectedPayloadEquatable.Equals(pushNotificationData.Payload) &&
|
||||||
|
pushNotificationData.ContextId == contextId;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class SyncNotificationEquals(Notification notification) : IEquatable<SyncNotificationPushNotification>
|
||||||
|
{
|
||||||
|
public bool Equals(SyncNotificationPushNotification? other)
|
||||||
|
{
|
||||||
|
return other != null &&
|
||||||
|
other.Id == notification.Id &&
|
||||||
|
other.UserId == notification.UserId &&
|
||||||
|
other.OrganizationId == notification.OrganizationId &&
|
||||||
|
other.ClientType == notification.ClientType &&
|
||||||
|
other.RevisionDate == notification.RevisionDate;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user