Skip to content

Commit

Permalink
VIH-10842 cache static data on start up (#1419)
Browse files Browse the repository at this point in the history
  • Loading branch information
shaed-parkar committed Aug 22, 2024
1 parent ad46ac5 commit 19372bc
Show file tree
Hide file tree
Showing 9 changed files with 344 additions and 22 deletions.
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
using System.Threading;
using System.Threading.Tasks;
using AdminWebsite.Controllers;
using BookingsApi.Client;
using AdminWebsite.Services;
using BookingsApi.Contract.V2.Responses;
using Microsoft.AspNetCore.Mvc;

namespace AdminWebsite.UnitTests.Controllers
{
public class HearingRolesControllerTests
{
private Mock<IBookingsApiClient> _bookingsApiClient;
private Mock<IReferenceDataService> _referenceDataService;
private HearingRolesController _controller;

[SetUp]
public void Setup()
{
_bookingsApiClient = new Mock<IBookingsApiClient>();
_controller = new HearingRolesController(_bookingsApiClient.Object);
_referenceDataService = new Mock<IReferenceDataService>();
_controller = new HearingRolesController(_referenceDataService.Object);
}

[Test]
Expand Down Expand Up @@ -44,10 +45,10 @@ public async Task Should_return_list_of_hearing_roles()
}
};

_bookingsApiClient.Setup(x => x.GetHearingRolesAsync()).ReturnsAsync(roles);
_referenceDataService.Setup(x => x.GetHearingRolesAsync(CancellationToken.None)).ReturnsAsync(roles);

// Act
var response = await _controller.GetHearingRoles();
var response = await _controller.GetHearingRoles(CancellationToken.None);

// Assert
var okResult = (OkObjectResult)response;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AdminWebsite.Configuration;
using Autofac.Extras.Moq;
Expand All @@ -8,6 +9,7 @@
using AdminWebsite.Mappers;
using AdminWebsite.Models;
using AdminWebsite.Security;
using AdminWebsite.Services;
using BookingsApi.Client;
using BookingsApi.Contract.Interfaces.Response;
using BookingsApi.Contract.V1.Enums;
Expand All @@ -20,6 +22,7 @@ namespace AdminWebsite.UnitTests.Controllers
public class ReferenceDataControllerTests
{
private Mock<IBookingsApiClient> _bookingsApiClientMock;
private Mock<IReferenceDataService> _referenceDataServiceMock;
private Mock<IUserIdentity> _userIdentityMock;
private Mock<IFeatureToggles> _featureTogglesMock;
private ReferenceDataController _controller;
Expand All @@ -32,14 +35,16 @@ public void Setup()
_bookingsApiClientMock = _mocker.Mock<IBookingsApiClient>();
_userIdentityMock = _mocker.Mock<IUserIdentity>();
_featureTogglesMock = _mocker.Mock<IFeatureToggles>();
_referenceDataServiceMock = _mocker.Mock<IReferenceDataService>();
_controller = _mocker.Create<ReferenceDataController>();
}

[Test]
public void Should_return_a_list_of_venues()
{
var hearingVenues = Builder<HearingVenueResponse>.CreateListOfSize(2).Build().ToList();
_bookingsApiClientMock.Setup(x => x.GetHearingVenuesAsync(true)).ReturnsAsync(hearingVenues);
_referenceDataServiceMock.Setup(x => x.GetHearingVenuesAsync(It.IsAny<CancellationToken>()))
.ReturnsAsync(hearingVenues);

var response = _controller.GetCourts();
var result = (OkObjectResult)response.Result.Result;
Expand All @@ -55,8 +60,8 @@ public async Task Should_return_all_hearing_types_and_case_types_where_hearing_t
var includeDeleted = true;
_userIdentityMock.Setup(x => x.IsATeamLead())
.Returns(true);
_bookingsApiClientMock.Setup(x =>
x.GetCaseTypesAsync(includeDeleted))
_referenceDataServiceMock.Setup(x =>
x.GetNonDeletedCaseTypesAsync(It.IsAny<CancellationToken>()))
.ReturnsAsync(GetCaseTypesList());

// Act
Expand All @@ -65,7 +70,6 @@ public async Task Should_return_all_hearing_types_and_case_types_where_hearing_t
// Assert
var okObjectResult = result.Result.Should().BeAssignableTo<OkObjectResult>().Which;
okObjectResult.Value.Should().BeEquivalentTo(GetHearingTypes());
_bookingsApiClientMock.Verify(x => x.GetCaseTypesAsync(includeDeleted), Times.Once);
}

[TestCase(true)]
Expand Down Expand Up @@ -148,7 +152,8 @@ public async Task should_return_list_of_available_languages()
};

var expected = languages.Select(AvailableLanguageResponseMapper.Map).ToList();
_bookingsApiClientMock.Setup(x => x.GetAvailableInterpreterLanguagesAsync()).ReturnsAsync(languages);
_referenceDataServiceMock.Setup(x => x.GetInterpreterLanguagesAsync(It.IsAny<CancellationToken>()))
.ReturnsAsync(languages);


// Act
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
using System.Threading;
using System.Threading.Tasks;
using AdminWebsite.Services;
using Autofac;
using Autofac.Extras.Moq;
using BookingsApi.Client;
using BookingsApi.Contract.V1.Enums;
using BookingsApi.Contract.V1.Responses;
using BookingsApi.Contract.V2.Responses;
using Microsoft.Extensions.Caching.Memory;

namespace AdminWebsite.UnitTests.Services;

public class ReferenceDataServiceTests
{
private AutoMock _mocker;
private ReferenceDataService _sut;
private IMemoryCache _memoryCache;

[SetUp]
public void Setup()
{
_memoryCache = new MemoryCache(new MemoryCacheOptions());
_mocker = AutoMock.GetLoose(builder => builder.RegisterInstance(_memoryCache).As<IMemoryCache>());
_sut = _mocker.Create<ReferenceDataService>();
}

[Test]
public async Task Should_initialise_cache()
{
// arrange
_mocker.Mock<IBookingsApiClient>().Setup(x => x.GetAvailableInterpreterLanguagesAsync(It.IsAny<CancellationToken>()))
.ReturnsAsync(new List<InterpreterLanguagesResponse>());
_mocker.Mock<IBookingsApiClient>().Setup(x => x.GetHearingVenuesAsync(true, It.IsAny<CancellationToken>()))
.ReturnsAsync(new List<HearingVenueResponse>());
_mocker.Mock<IBookingsApiClient>().Setup(x => x.GetCaseTypesAsync(false, It.IsAny<CancellationToken>()))
.ReturnsAsync(new List<CaseTypeResponse>());
_mocker.Mock<IBookingsApiClient>().Setup(x => x.GetHearingRolesAsync(It.IsAny<CancellationToken>()))
.ReturnsAsync(new List<HearingRoleResponseV2>());

// act
await _sut.InitialiseCache();

// assert
_mocker.Mock<IBookingsApiClient>().Verify(x => x.GetAvailableInterpreterLanguagesAsync(It.IsAny<CancellationToken>()), Times.Once);
_mocker.Mock<IBookingsApiClient>().Verify(x => x.GetHearingVenuesAsync(true, It.IsAny<CancellationToken>()), Times.Once);
_mocker.Mock<IBookingsApiClient>().Verify(x => x.GetCaseTypesAsync(false, It.IsAny<CancellationToken>()), Times.Once);
_mocker.Mock<IBookingsApiClient>().Verify(x => x.GetHearingRolesAsync(It.IsAny<CancellationToken>()), Times.Once);
}

[Test]
public async Task should_return_non_deleted_case_types()
{
var caseTypes = new List<CaseTypeResponse>
{
new ()
{
Id = 1, Name = "type1", ServiceId = "AA1",
HearingTypes =
[
new() { Id = 10, Name = "HType10", Code = "Code10" }
]
},
new()
{
Id = 2, Name = "type2", ServiceId = "AA2",
HearingTypes =
[
new() { Id = 20, Name = "HType20", Code = "Code20" }
]
},
new()
{
Id = 3, Name = "type3", ServiceId = "AA3",
HearingTypes =
[
new() { Id = 25, Name = "HType25", Code = "Code25" },
new() { Id = 29, Name = "HType29", Code = "Code29" }
]
},
new()
{
Id = 4, Name = "type4", ServiceId = "AA4",
HearingTypes = new List<HearingTypeResponse>()
}
};

_mocker.Mock<IBookingsApiClient>().Setup(x => x.GetCaseTypesAsync(false, It.IsAny<CancellationToken>()))
.ReturnsAsync(caseTypes);

// act
var result = await _sut.GetNonDeletedCaseTypesAsync();

// assert
result.Count.Should().Be(caseTypes.Count);
result[0].Id.Should().Be(caseTypes[0].Id);
result[0].Name.Should().Be(caseTypes[0].Name);
result[0].ServiceId.Should().Be(caseTypes[0].ServiceId);
}

[Test]
public async Task GetHearingRolesAsync_ReturnsExpectedData()
{
// Arrange
var expectedHearingRoles = new List<HearingRoleResponseV2>
{
new() { Name = "Applicant", UserRole = "Individual", Code = "APPL" },
new() { Name = "Applicant", UserRole = "Appellant", Code = "APEL" },
};

_mocker.Mock<IBookingsApiClient>()
.Setup(x => x.GetHearingRolesAsync(It.IsAny<CancellationToken>()))
.ReturnsAsync(expectedHearingRoles);

// Act
var result = await _sut.GetHearingRolesAsync();

// Assert
result.Should().BeEquivalentTo(expectedHearingRoles);
}

[Test]
public async Task Should_return_interpreter_languages()
{
// arrange
var languages = new List<InterpreterLanguagesResponse>
{
new ()
{
Code = "spa",
Value = "Spanish",
Type = InterpreterType.Verbal
},
new ()
{
Code = "urd",
Value = "Urdu",
Type = InterpreterType.Verbal
}
};
_mocker.Mock<IBookingsApiClient>().Setup(x => x.GetAvailableInterpreterLanguagesAsync(It.IsAny<CancellationToken>())).ReturnsAsync(languages);

// act
var result = await _sut.GetInterpreterLanguagesAsync();

// assert
result.Count.Should().Be(languages.Count);
result[0].Code.Should().Be(languages[0].Code);
result[0].Value.Should().Be(languages[0].Value);
result[0].Type.Should().Be(languages[0].Type);
}

[Test]
public async Task should_return_hearing_venues_for_today()
{
// arrange
var hearingVenues = new List<HearingVenueResponse>
{
new()
{
Id = 1,
Name = "Venue 1",
Code = "123456"
},
new()
{
Id = 2,
Name = "Venue 2",
Code = "234567"
}
};
_mocker.Mock<IBookingsApiClient>().Setup(x => x.GetHearingVenuesAsync(true, It.IsAny<CancellationToken>()))
.ReturnsAsync(hearingVenues);

// act
var result = await _sut.GetHearingVenuesAsync();

// assert
result.Count.Should().Be(hearingVenues.Count);
result[0].Id.Should().Be(hearingVenues[0].Id);
result[0].Name.Should().Be(hearingVenues[0].Name);
result[0].Code.Should().Be(hearingVenues[0].Code);
}

[Test]
public async Task Should_not_call_api_again_when_cache_value_exists()
{
var hearingVenues = new List<HearingVenueResponse>
{
new()
{
Id = 1,
Name = "Venue 1",
Code = "123456"
},
new()
{
Id = 2,
Name = "Venue 2",
Code = "234567"
}
};
_mocker.Mock<IBookingsApiClient>().Setup(x => x.GetHearingVenuesAsync(true, It.IsAny<CancellationToken>()))
.ReturnsAsync(hearingVenues);

// act
await _sut.GetHearingVenuesAsync();
await _sut.GetHearingVenuesAsync();

// assert
_mocker.Mock<IBookingsApiClient>().Verify(x => x.GetHearingVenuesAsync(true, It.IsAny<CancellationToken>()), Times.Once);
}
}
15 changes: 7 additions & 8 deletions AdminWebsite/AdminWebsite/Controllers/HearingRolesController.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using AdminWebsite.Contracts.Responses;
using AdminWebsite.Mappers;
using BookingsApi.Client;
using AdminWebsite.Services;
using Microsoft.AspNetCore.Mvc;
using Swashbuckle.AspNetCore.Annotations;

Expand All @@ -15,22 +16,20 @@ namespace AdminWebsite.Controllers
[ApiController]
public class HearingRolesController : ControllerBase
{
private readonly IBookingsApiClient _bookingsApiClient;
private readonly IReferenceDataService _referenceDataService;

public HearingRolesController(IBookingsApiClient bookingsApiClient)
public HearingRolesController(IReferenceDataService referenceDataService)
{
_bookingsApiClient = bookingsApiClient;
_referenceDataService = referenceDataService;
}

[HttpGet]
[SwaggerOperation(OperationId = "GetHearingRoles")]
[ProducesResponseType(typeof(List<HearingRoleResponse>), (int) HttpStatusCode.OK)]
public async Task<IActionResult> GetHearingRoles()
public async Task<IActionResult> GetHearingRoles(CancellationToken cancellationToken)
{
var hearingRoles = await _bookingsApiClient.GetHearingRolesAsync();

var hearingRoles = await _referenceDataService.GetHearingRolesAsync(cancellationToken);
var response = hearingRoles.Select(item => item.Map()).ToList();

return Ok(response);
}
}
Expand Down
Loading

0 comments on commit 19372bc

Please sign in to comment.