Skip to content
Open
Show file tree
Hide file tree
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
using System.Net;
using System.Net.Http.Json;
using System.Text.Json.Nodes;

using AAS.TwinEngine.DataEngine.ApplicationLogic.Exceptions.Base;
using AAS.TwinEngine.DataEngine.ApplicationLogic.Exceptions.Infrastructure;
using AAS.TwinEngine.DataEngine.ApplicationLogic.Services.Description;
using AAS.TwinEngine.DataEngine.ApplicationLogic.Services.Plugin;
using AAS.TwinEngine.DataEngine.ApplicationLogic.Services.Plugin.Providers;
using AAS.TwinEngine.DataEngine.DomainModel.Description;
using AAS.TwinEngine.DataEngine.ModuleTests.Common;

using Microsoft.Extensions.DependencyInjection;

using NSubstitute;
using NSubstitute.ExceptionExtensions;

namespace AAS.TwinEngine.DataEngine.ModuleTests.Api.Services.Description;

public abstract class DescriptionControllerTests : IDisposable
{
private readonly ConfigTestFactory _factory;
private readonly IDescriptionService _mockDescriptionService;
private readonly HttpClient _client;
private readonly IPluginManifestProvider _mockPluginManifestProvider;
private readonly IPluginManifestConflictHandler _mockPluginManifestConflictHandler;

protected DescriptionControllerTests(string configDir)
{
_mockDescriptionService = Substitute.For<IDescriptionService>();

_mockPluginManifestProvider = Substitute.For<IPluginManifestProvider>();
_mockPluginManifestConflictHandler = Substitute.For<IPluginManifestConflictHandler>();

_factory = new ConfigTestFactory(configDir, services =>
{
_ = services.AddSingleton(_mockDescriptionService);
_ =services.AddSingleton(_mockPluginManifestProvider);
_ = services.AddSingleton(_mockPluginManifestConflictHandler);
});

_client = _factory.CreateClient();
_ = _mockPluginManifestConflictHandler.Manifests.Returns([]);
}

public void Dispose()
{
_client.Dispose();
_factory.Dispose();
GC.SuppressFinalize(this);
}

[Fact]
public async Task GetDescriptor_ReturnsOkAsync()
{
_ = _mockDescriptionService
.GetDescriptor(Arg.Any<CancellationToken>())
.Returns(new ServiceDescription
{
Profiles =
[
"https://admin-shell.io/aas/API/3/1/AssetAdministrationShellRegistryServiceSpecification/SSP-002"
]
});

var response = await _client.GetAsync("/description");

Assert.Equal(HttpStatusCode.OK, response.StatusCode);

var json = await response.Content.ReadFromJsonAsync<JsonObject>();

Assert.NotNull(json);
}

[Fact]
public async Task GetDescriptor_WhenForbidden_Returns403Async()
{
_ = _mockDescriptionService
.GetDescriptor(Arg.Any<CancellationToken>())
.Throws(new ForbiddenException());

var response = await _client.GetAsync("/description");

Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode);
}

[Fact]
public async Task GetDescriptor_WhenInternalServerError_Returns500Async()
{
_ = _mockDescriptionService
.GetDescriptor(Arg.Any<CancellationToken>())
.Throws(new ResponseParsingException());

var response = await _client.GetAsync("/description");

Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
}
}

public class DescriptionControllerTestsV1Config() : DescriptionControllerTests("v1-config");

public class DescriptionControllerTestsV2Config() : DescriptionControllerTests("v2-config");
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
using System.Net;
using System.Net.Http.Json;
using System.Text;
using System.Text.Json;
using System.Text.Json.Nodes;

using AAS.TwinEngine.DataEngine.Api.Discovery.Requests;
Expand All @@ -13,9 +11,6 @@
using AAS.TwinEngine.DataEngine.ModuleTests.Common;
using AAS.TwinEngine.DataEngine.ServiceConfiguration.Config;

using AasCore.Aas3_1;

using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Extensions.DependencyInjection;

using NSubstitute;
Expand Down Expand Up @@ -177,29 +172,6 @@ private void SetupPluginHttpClient(string pluginResponse)
const string HttpClientName = $"{HttpClientNames.PluginDataProviderPrefix}TestPlugin1";
_ = _httpClientFactory.CreateClient(HttpClientName).Returns(httpClient);
}

private void SetupPluginHttpClientNotCalled()
{
const string HttpClientName = $"{HttpClientNames.PluginDataProviderPrefix}TestPlugin1";
_ = _httpClientFactory.CreateClient(HttpClientName).Returns((HttpClient)null!);
}

private void SetupTemplateProvider()
{
_ = _mockTemplateService.GetShellTemplateAsync(Arg.Any<string>(), Arg.Any<CancellationToken>())
.Returns(callInfo => new AssetAdministrationShell(
callInfo.ArgAt<string>(0),
new AssetInformation(AssetKind.Instance))
{
Submodels =
[
new Reference(ReferenceTypes.ModelReference,
[
new Key(KeyTypes.Submodel, "urn:example:sm:nameplate:001")
])
]
});
}
}

public class DiscoveryControllerTestsV2Config() : DiscoveryControllerTests("v2-config");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using AAS.TwinEngine.DataEngine.Api.Description;
using AAS.TwinEngine.DataEngine.Api.Description.Handler;
using AAS.TwinEngine.DataEngine.Api.Description.Responses;
using AAS.TwinEngine.DataEngine.ApplicationLogic.Exceptions.Base;

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;

using NSubstitute;
using NSubstitute.ExceptionExtensions;

namespace AAS.TwinEngine.DataEngine.UnitTests.Api.Description;

public class DescriptionControllerTests
{
private readonly IDescriptionHandler _handler;
private readonly DescriptionController _sut;

public DescriptionControllerTests()
{
var logger = Substitute.For<ILogger<DescriptionController>>();
_handler = Substitute.For<IDescriptionHandler>();

_sut = new DescriptionController(logger, _handler);
}

[Fact]
public void GetDescriptor_ReturnsOkResult()
{
var expected = new ServiceDescriptionDto
{
Profiles =
[
"https://admin-shell.io/aas/API/3/1/AssetAdministrationShellRegistryServiceSpecification/SSP-002",
"https://admin-shell.io/aas/API/3/1/AssetAdministrationShellRepositoryServiceSpecification/SSP-002",
"https://admin-shell.io/aas/API/3/1/SubmodelRegistryServiceSpecification/SSP-002",
"https://admin-shell.io/aas/API/3/1/SubmodelRepositoryServiceSpecification/SSP-002",
"https://admin-shell.io/aas/API/3/1/DiscoveryServiceSpecification/SSP-002"
]
};

_handler
.GetDescriptor(Arg.Any<CancellationToken>())
.Returns(expected);

var result = _sut.GetDescriptor(CancellationToken.None);

var okResult = Assert.IsType<OkObjectResult>(result.Result);
var dto = Assert.IsType<ServiceDescriptionDto>(okResult.Value);

Assert.Equal(expected, dto);
}

[Fact]
public void GetDescriptor_ReturnsOkWithNull_WhenHandlerReturnsNull()
{
_handler
.GetDescriptor(Arg.Any<CancellationToken>())
.Returns((ServiceDescriptionDto?)null);

var result = _sut.GetDescriptor(CancellationToken.None);

var okResult = Assert.IsType<OkObjectResult>(result.Result);

Assert.Null(okResult.Value);
}

[Fact]
public void GetDescriptor_ThrowsForbiddenException()
{
_handler
.GetDescriptor(Arg.Any<CancellationToken>())
.Throws(new ForbiddenException("Forbidden"));

var ex = Record.Exception(() =>
_sut.GetDescriptor(CancellationToken.None));

Assert.IsType<ForbiddenException>(ex);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using AAS.TwinEngine.DataEngine.Api.Description.Handler;
using AAS.TwinEngine.DataEngine.ApplicationLogic.Services.Description;
using AAS.TwinEngine.DataEngine.DomainModel.Description;

using Microsoft.Extensions.Logging;

using NSubstitute;

namespace AAS.TwinEngine.DataEngine.UnitTests.Api.Description.Handler;

public class DescriptionHandlerTests
{
private readonly ILogger<DescriptionHandler> _logger;
private readonly IDescriptionService _descriptionService;
private readonly DescriptionHandler _sut;

public DescriptionHandlerTests()
{
_logger = Substitute.For<ILogger<DescriptionHandler>>();
_descriptionService = Substitute.For<IDescriptionService>();

_sut = new DescriptionHandler(_logger, _descriptionService);
}

[Fact]
public void GetDescriptor_ReturnsExpectedDto()
{
var descriptor = new ServiceDescription
{
Profiles =
[
"https://admin-shell.io/aas/API/3/1/AssetAdministrationShellRegistryServiceSpecification/SSP-002",
"https://admin-shell.io/aas/API/3/1/AssetAdministrationShellRepositoryServiceSpecification/SSP-002",
"https://admin-shell.io/aas/API/3/1/SubmodelRegistryServiceSpecification/SSP-002",
"https://admin-shell.io/aas/API/3/1/SubmodelRepositoryServiceSpecification/SSP-002",
"https://admin-shell.io/aas/API/3/1/DiscoveryServiceSpecification/SSP-002"
]
};

_descriptionService
.GetDescriptor(Arg.Any<CancellationToken>())
.Returns(descriptor);

var result = _sut.GetDescriptor(CancellationToken.None);

Assert.NotNull(result);
Assert.Equal(descriptor.Profiles, result.Profiles);
}

[Fact]
public void GetDescriptor_CallsServiceOnce()
{
_descriptionService
.GetDescriptor(Arg.Any<CancellationToken>())
.Returns(new ServiceDescription());

_sut.GetDescriptor(CancellationToken.None);

_descriptionService.Received(1)
.GetDescriptor(CancellationToken.None);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using AAS.TwinEngine.DataEngine.Api.Description.MappingProfiles;
using AAS.TwinEngine.DataEngine.DomainModel.Description;

namespace AAS.TwinEngine.DataEngine.UnitTests.Api.Description.MappingProfiles;

public class ServiceDescriptionMapperProfileTests
{
[Fact]
public void ToDto_WithProfiles_ReturnsMappedDto()
{
var serviceDescription = new ServiceDescription
{
Profiles =
[
"https://admin-shell.io/aas/API/3/1/AssetAdministrationShellRegistryServiceSpecification/SSP-002",
"https://admin-shell.io/aas/API/3/1/SubmodelRegistryServiceSpecification/SSP-002"
]
};

var result = serviceDescription.ToDto();

Assert.NotNull(result);
Assert.Equal(serviceDescription.Profiles, result.Profiles);
}

[Fact]
public void ToDto_WithNullProfiles_ReturnsEmptyProfilesCollection()
{
var serviceDescription = new ServiceDescription
{
Profiles = null
};

var result = serviceDescription.ToDto();

Assert.NotNull(result);
Assert.NotNull(result.Profiles);
Assert.Empty(result.Profiles);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using AAS.TwinEngine.DataEngine.ApplicationLogic.Services.Description;

namespace AAS.TwinEngine.DataEngine.UnitTests.ApplicationLogic.Services.Description;

public class DescriptionServiceTests
{
private static readonly string[] ExpectedProfiles =
[
"https://admin-shell.io/aas/API/3/1/AssetAdministrationShellRegistryServiceSpecification/SSP-002",
"https://admin-shell.io/aas/API/3/1/AssetAdministrationShellRepositoryServiceSpecification/SSP-002",
"https://admin-shell.io/aas/API/3/1/SubmodelRegistryServiceSpecification/SSP-002",
"https://admin-shell.io/aas/API/3/1/SubmodelRepositoryServiceSpecification/SSP-002",
"https://admin-shell.io/aas/API/3/1/DiscoveryServiceSpecification/SSP-002"
];

[Fact]
public void GetDescriptor_WhenCalled_ReturnsAllFiveSspProfiles()
{
var sut = new DescriptionService();

var result = sut.GetDescriptor(CancellationToken.None);

Assert.NotNull(result);
Assert.NotNull(result.Profiles);
Assert.Equal(5, result.Profiles!.Count);
Assert.Equal(ExpectedProfiles, result.Profiles);
}
}
Loading
Loading