Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix nesting in entity registry service, add unit tests #35

Merged
merged 1 commit into from
Mar 21, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions Dan.Common.UnitTest/Dan.Common.UnitTest.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
<PackageReference Include="Moq" Version="4.18.2" />
<PackageReference Include="MSTest.TestAdapter" Version="2.2.8" />
<PackageReference Include="MSTest.TestFramework" Version="2.2.8" />
<PackageReference Include="coverlet.collector" Version="3.1.2" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Dan.Common\Dan.Common.csproj" />
</ItemGroup>

</Project>
209 changes: 209 additions & 0 deletions Dan.Common.UnitTest/Services/EntityRegistryServiceTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
namespace Dan.Common.UnitTest.Services;

[TestClass]
[ExcludeFromCodeCoverage]
public class EntityRegistryServiceTest
{
private readonly Mock<IEntityRegistryApiClientService> _entityRegistryApiClientServiceMock = new();
private readonly IEntityRegistryService _entityRegistryService;

public EntityRegistryServiceTest()
{
_entityRegistryService = new EntityRegistryService(_entityRegistryApiClientServiceMock.Object);
}

[TestInitialize]
public void TestInitialize()
{
_entityRegistryApiClientServiceMock.Setup(_ => _.GetUpstreamEntityRegistryUnitAsync(It.IsAny<Uri>()))
.Returns((Uri url) =>
{
var orgForm = new Organisasjonsform { Kode = "AS" };
if (url.AbsolutePath.Contains("/enheter/91"))
{
return Task.FromResult(new EntityRegistryUnit { Organisasjonsnummer = "91", Organisasjonsform = orgForm })!;
}

if (url.AbsolutePath.Contains("/underenheter/92"))
{
return Task.FromResult(new EntityRegistryUnit { Organisasjonsnummer = "92", OverordnetEnhet = "91", Organisasjonsform = orgForm })!;
}

// Only subunits are at the leaf node, any nested parents are MainUnits
// Example: https://data.brreg.no/enhetsregisteret/api/underenheter/879587662
if (url.AbsolutePath.Contains("/enheter/93"))
{
return Task.FromResult(new EntityRegistryUnit { Organisasjonsnummer = "93", OverordnetEnhet = "91", Organisasjonsform = orgForm })!;
}

if (url.AbsolutePath.Contains("/underenheter/94"))
{
return Task.FromResult(new EntityRegistryUnit { Organisasjonsnummer = "94", OverordnetEnhet = "93", Organisasjonsform = orgForm })!;
}

if (url.AbsolutePath.Contains("/underenheter/31"))
{
return Task.FromResult(new EntityRegistryUnit { Organisasjonsnummer = "31", Organisasjonsform = orgForm })!;
}

return Task.FromResult<EntityRegistryUnit?>(null);
});
}

[TestMethod]
public void TestGetMapping()
{
var s = new EntityRegistryService(_entityRegistryApiClientServiceMock.Object) { UseCoreProxy = false };
var r = s.Get("91").Result;
Assert.AreEqual("91", r?.OrganizationNumber);
}

[TestMethod]
public void TestGetAttemptSubUnitLookupIfNotFoundReturnsSubUnit()
{
var s = new EntityRegistryService(_entityRegistryApiClientServiceMock.Object) { UseCoreProxy = false };
var r = s.Get("92").Result;
Assert.AreEqual("92", r?.OrganizationNumber);
}

[TestMethod]
public void TestGetAttemptSubUnitLookupIfNotFoundSetToFalseReturnsNull()
{
var s = new EntityRegistryService(_entityRegistryApiClientServiceMock.Object) { UseCoreProxy = false };
var r = s.Get("92", attemptSubUnitLookupIfNotFound: false).Result;
Assert.IsNull(r);
}

[TestMethod]
public void TestGetMainUnit()
{
var s = new EntityRegistryService(_entityRegistryApiClientServiceMock.Object) { UseCoreProxy = false };
var r = s.GetMainUnit("91").Result;
Assert.AreEqual("91", r?.OrganizationNumber);
}

[TestMethod]
public void TestGetMainUnitAttemptsSubunitLookup()
{
var s = new EntityRegistryService(_entityRegistryApiClientServiceMock.Object) { UseCoreProxy = false };
var r = s.GetMainUnit("92").Result;
Assert.AreEqual("91", r?.OrganizationNumber);
}

[TestMethod]
public void TestGetFullMainAttemptsSubunitLookup()
{
var s = new EntityRegistryService(_entityRegistryApiClientServiceMock.Object) { UseCoreProxy = false };
var r = s.GetFullMainUnit("92").Result;
Assert.AreEqual("91", r?.Organisasjonsnummer);
}

[TestMethod]
public void TestGetSubUnitOnlyReturnsSubunit()
{
var s = new EntityRegistryService(_entityRegistryApiClientServiceMock.Object) { UseCoreProxy = false };
var r = s.Get("92", subUnitOnly: true).Result;
Assert.AreEqual("92", r?.OrganizationNumber);
}

[TestMethod]
public void TestGetSubUnitOnlyReturnsNullIfMainUnit()
{
var s = new EntityRegistryService(_entityRegistryApiClientServiceMock.Object) { UseCoreProxy = false };
var r = s.Get("91", subUnitOnly: true).Result;
Assert.IsNull(r);
}

[TestMethod]
public void TestGetNestToTopmostMainUnitReturnsMainunit()
{
var s = new EntityRegistryService(_entityRegistryApiClientServiceMock.Object) { UseCoreProxy = false };
var r = s.GetMainUnit("94").Result;
Assert.AreEqual("91", r?.OrganizationNumber);
}

[TestMethod]
public void TestSyntheticLookupsNotAllowedByDefault()
{
var s = new EntityRegistryService(_entityRegistryApiClientServiceMock.Object) { UseCoreProxy = false };
var r = s.GetMainUnit("31").Result;
Assert.IsNull(r);
}

[TestMethod]
public void TestIsMainUnit()
{
var s = new EntityRegistryService(_entityRegistryApiClientServiceMock.Object) { UseCoreProxy = false };
var r = s.IsMainUnit("91").Result;
Assert.IsTrue(r);
}

[TestMethod]
public void TestIsMainUnitSimpleObj()
{
var s = new EntityRegistryService(_entityRegistryApiClientServiceMock.Object) { UseCoreProxy = false };
var r = s.IsMainUnit(new SimpleEntityRegistryUnit());
Assert.IsTrue(r);
}

[TestMethod]
public void TestIsMainUnitFullObj()
{
var s = new EntityRegistryService(_entityRegistryApiClientServiceMock.Object) { UseCoreProxy = false };
var r = s.IsMainUnit(new EntityRegistryUnit { Organisasjonsnummer = "91", Organisasjonsform = new Organisasjonsform { Kode = "AS" } });
Assert.IsTrue(r);
}

[TestMethod]
public void TestIsSubUnit()
{
var s = new EntityRegistryService(_entityRegistryApiClientServiceMock.Object) { UseCoreProxy = false };
var r = s.IsSubUnit("92").Result;
Assert.IsTrue(r);
}

[TestMethod]
public void TestIsSubUnitSimpleObj()
{
var s = new EntityRegistryService(_entityRegistryApiClientServiceMock.Object) { UseCoreProxy = false };
var r = s.IsSubUnit(new SimpleEntityRegistryUnit { ParentUnit = "x" });
Assert.IsTrue(r);
}

[TestMethod]
public void TestIsSubUnitFullObj()
{
var s = new EntityRegistryService(_entityRegistryApiClientServiceMock.Object) { UseCoreProxy = false };
var r = s.IsSubUnit(new EntityRegistryUnit { Organisasjonsnummer = "91", Organisasjonsform = new Organisasjonsform { Kode = "AS" }, OverordnetEnhet = "x" });
Assert.IsTrue(r);
}

[DataTestMethod]
[DataRow("971032146", "AS", "0000", "0000", true)] // Public sector organization from PublicSectorOrganizations
[DataRow("123456789", "KF", "0000", "0000", true)] // Public sector unit type
[DataRow("123456789", "AS", "3900", "0000", true)] // Public sector sector code
[DataRow("123456789", "AS", "0000", "8411", true)] // Public sector industrial code
[DataRow("123456789", "AS", "0000", "0000", false)] // Non-public sector organization
public void TestIsPublicAgency(
string organizationNumber,
string organizationForm,
string sectorCode,
string industrialCode1,
bool expectedResult)
{
// Arrange
var entityRegistryUnit = new SimpleEntityRegistryUnit
{
OrganizationNumber = organizationNumber,
OrganizationForm = organizationForm,
SectorCode = sectorCode,
IndustrialCodes = new List<string> { industrialCode1 }
};

// Act
var isPublicAgency = _entityRegistryService.IsPublicAgency(entityRegistryUnit);

// Assert
Assert.AreEqual(expectedResult, isPublicAgency);
}
}
6 changes: 6 additions & 0 deletions Dan.Common.UnitTest/Usings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
global using Microsoft.VisualStudio.TestTools.UnitTesting;
global using System.Diagnostics.CodeAnalysis;
global using Dan.Common.Interfaces;
global using Dan.Common.Models;
global using Dan.Common.Services;
global using Moq;
46 changes: 29 additions & 17 deletions Dan.Common/Services/EntityRegistryService.cs
Original file line number Diff line number Diff line change
@@ -59,32 +59,44 @@ public EntityRegistryService(IEntityRegistryApiClientService entityRegistryApiCl
}

EntityRegistryUnit? unit;
// We only want a subunit, so try that and return regardless
if (subUnitOnly)
{
unit = await InternalGet(organizationNumber, UnitType.SubUnit);
if (unit == null) return null;

if (nestToAndReturnMainUnit && unit.OverordnetEnhet != null)
{
var parentUnit = unit;
do
{
parentUnit = await InternalGet(parentUnit.OverordnetEnhet, UnitType.MainUnit);
}
while (parentUnit!.OverordnetEnhet != null);

return parentUnit;
}
return await InternalGet(organizationNumber, UnitType.SubUnit);
}

// At this point we return a mainunit if we find one
unit = await InternalGet(organizationNumber, UnitType.MainUnit);
if (unit == null && attemptSubUnitLookupIfNotFound)
if (unit != null)
{
return await InternalGet(organizationNumber, UnitType.SubUnit);
return unit;
}

// Didn't find a main unit, check if we should check if it's a subunit
// or nest to topmost parent
if (attemptSubUnitLookupIfNotFound || nestToAndReturnMainUnit) {
unit = await InternalGet(organizationNumber, UnitType.SubUnit);
}

// If we didn't find any subunit at this point or we're not supposed
// to nest, return at this point
if (unit == null || !nestToAndReturnMainUnit)
{
return unit;
}

// We did find a subunit, and we're instructed to nest to the top mainunit
var parentUnit = unit;
do
{
// Only subunits are at the leaf node, any nested parents are MainUnits
// Example: https://data.brreg.no/enhetsregisteret/api/underenheter/879587662
parentUnit = await InternalGet(parentUnit.OverordnetEnhet!, UnitType.MainUnit);
}
while (parentUnit?.OverordnetEnhet != null);
unit = parentUnit;

return unit;

}

public async Task<EntityRegistryUnit?> GetFullMainUnit(string organizationNumber) => await GetFull(organizationNumber, attemptSubUnitLookupIfNotFound: false, nestToAndReturnMainUnit: true);
6 changes: 6 additions & 0 deletions Dan.sln
Original file line number Diff line number Diff line change
@@ -12,6 +12,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dan.Common", "Dan.Common\Da
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dan.Core.UnitTest", "Dan.Core.UnitTest\Dan.Core.UnitTest.csproj", "{CD43EC26-1570-475D-8A05-4D8CC4BB6810}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dan.Common.UnitTest", "Dan.Common.UnitTest\Dan.Common.UnitTest.csproj", "{9B7CB8FD-7827-48D6-895E-0F79C27FD0EE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -30,6 +32,10 @@ Global
{CD43EC26-1570-475D-8A05-4D8CC4BB6810}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CD43EC26-1570-475D-8A05-4D8CC4BB6810}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CD43EC26-1570-475D-8A05-4D8CC4BB6810}.Release|Any CPU.Build.0 = Release|Any CPU
{9B7CB8FD-7827-48D6-895E-0F79C27FD0EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9B7CB8FD-7827-48D6-895E-0F79C27FD0EE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9B7CB8FD-7827-48D6-895E-0F79C27FD0EE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9B7CB8FD-7827-48D6-895E-0F79C27FD0EE}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE