测试 gRPC 购物车服务
This commit is contained in:
parent
c192d209fd
commit
680ce10fa7
@ -27,9 +27,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HelloShop.ProductService.Un
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HelloShop.ProductService.FunctionalTests", "tests\HelloShop.ProductService.FunctionalTests\HelloShop.ProductService.FunctionalTests.csproj", "{45932B7F-6ED0-40F3-AA2C-F14A844FEE18}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HelloShop.ProductService.FunctionalTests", "tests\HelloShop.ProductService.FunctionalTests\HelloShop.ProductService.FunctionalTests.csproj", "{45932B7F-6ED0-40F3-AA2C-F14A844FEE18}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HelloShop.HybridApp", "src\HelloShop.HybridApp\HelloShop.HybridApp.csproj", "{E58F82E2-2E48-459B-A40E-497F24FC6DC1}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HelloShop.HybridApp", "src\HelloShop.HybridApp\HelloShop.HybridApp.csproj", "{E58F82E2-2E48-459B-A40E-497F24FC6DC1}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HelloShop.FunctionalTests", "tests\HelloShop.FunctionalTests\HelloShop.FunctionalTests.csproj", "{6BAA9747-E0D0-41B9-8A1B-88B777498C43}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HelloShop.FunctionalTests", "tests\HelloShop.FunctionalTests\HelloShop.FunctionalTests.csproj", "{6BAA9747-E0D0-41B9-8A1B-88B777498C43}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HelloShop.BasketService.UnitTests", "tests\HelloShop.BasketService.UnitTests\HelloShop.BasketService.UnitTests.csproj", "{BE88233A-D6EB-462B-B53C-B588A0BEFAFC}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HelloShop.BasketService.FunctionalTests", "tests\HelloShop.BasketService.FunctionalTests\HelloShop.BasketService.FunctionalTests.csproj", "{A0903D4D-EA4E-433A-AC5B-BE6ED4A5C958}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
@ -87,6 +91,14 @@ Global
|
|||||||
{6BAA9747-E0D0-41B9-8A1B-88B777498C43}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{6BAA9747-E0D0-41B9-8A1B-88B777498C43}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{6BAA9747-E0D0-41B9-8A1B-88B777498C43}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{6BAA9747-E0D0-41B9-8A1B-88B777498C43}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{6BAA9747-E0D0-41B9-8A1B-88B777498C43}.Release|Any CPU.Build.0 = Release|Any CPU
|
{6BAA9747-E0D0-41B9-8A1B-88B777498C43}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{BE88233A-D6EB-462B-B53C-B588A0BEFAFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{BE88233A-D6EB-462B-B53C-B588A0BEFAFC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{BE88233A-D6EB-462B-B53C-B588A0BEFAFC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{BE88233A-D6EB-462B-B53C-B588A0BEFAFC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{A0903D4D-EA4E-433A-AC5B-BE6ED4A5C958}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{A0903D4D-EA4E-433A-AC5B-BE6ED4A5C958}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{A0903D4D-EA4E-433A-AC5B-BE6ED4A5C958}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{A0903D4D-EA4E-433A-AC5B-BE6ED4A5C958}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@ -104,6 +116,8 @@ Global
|
|||||||
{45932B7F-6ED0-40F3-AA2C-F14A844FEE18} = {29BE158E-825E-48AB-A02D-4E537A5DC502}
|
{45932B7F-6ED0-40F3-AA2C-F14A844FEE18} = {29BE158E-825E-48AB-A02D-4E537A5DC502}
|
||||||
{E58F82E2-2E48-459B-A40E-497F24FC6DC1} = {1AD03316-A743-4E9D-B3BC-FB9499D15141}
|
{E58F82E2-2E48-459B-A40E-497F24FC6DC1} = {1AD03316-A743-4E9D-B3BC-FB9499D15141}
|
||||||
{6BAA9747-E0D0-41B9-8A1B-88B777498C43} = {29BE158E-825E-48AB-A02D-4E537A5DC502}
|
{6BAA9747-E0D0-41B9-8A1B-88B777498C43} = {29BE158E-825E-48AB-A02D-4E537A5DC502}
|
||||||
|
{BE88233A-D6EB-462B-B53C-B588A0BEFAFC} = {29BE158E-825E-48AB-A02D-4E537A5DC502}
|
||||||
|
{A0903D4D-EA4E-433A-AC5B-BE6ED4A5C958} = {29BE158E-825E-48AB-A02D-4E537A5DC502}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {845545A8-2006-46C3-ABD7-5BDF63F3858C}
|
SolutionGuid = {845545A8-2006-46C3-ABD7-5BDF63F3858C}
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
// See the license file in the project root for more information.
|
// See the license file in the project root for more information.
|
||||||
|
|
||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
using FluentValidation.Validators;
|
|
||||||
using HelloShop.BasketService.Protos;
|
using HelloShop.BasketService.Protos;
|
||||||
|
|
||||||
namespace HelloShop.BasketService.Validations.Baskets
|
namespace HelloShop.BasketService.Validations.Baskets
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
// Copyright (c) HelloShop Corporation. All rights reserved.
|
||||||
|
// See the license file in the project root for more information.
|
||||||
|
|
||||||
|
using Grpc.Core;
|
||||||
|
using Grpc.Core.Interceptors;
|
||||||
|
using Microsoft.Net.Http.Headers;
|
||||||
|
|
||||||
|
namespace HelloShop.BasketService.FunctionalTests
|
||||||
|
{
|
||||||
|
internal class AuthenticatedInterceptor : Interceptor
|
||||||
|
{
|
||||||
|
public override AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(TRequest request, ClientInterceptorContext<TRequest, TResponse> context, AsyncUnaryCallContinuation<TRequest, TResponse> continuation)
|
||||||
|
{
|
||||||
|
const string token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1laWQiOiIxIiwidW5pcXVlX25hbWUiOiJhZG1pbiIsInJvbGVpZCI6IjEiLCJuYmYiOjE3MjA1NzY3NDYsImV4cCI6MTc0MjYwODc0NiwiaWF0IjoxNzIwNTc2NzQ2fQ.ju_D3zeGLKqJYVckbb8Y3yNkp40nOqRAJrdOsISs4d4";
|
||||||
|
|
||||||
|
Metadata headers = [new Metadata.Entry(HeaderNames.Authorization, $"Bearer {token}")];
|
||||||
|
|
||||||
|
var newOptions = context.Options.WithHeaders(headers);
|
||||||
|
|
||||||
|
var newContext = new ClientInterceptorContext<TRequest, TResponse>(context.Method, context.Host, newOptions);
|
||||||
|
|
||||||
|
return base.AsyncUnaryCall(request, newContext, continuation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
// Copyright (c) HelloShop Corporation. All rights reserved.
|
||||||
|
// See the license file in the project root for more information.
|
||||||
|
|
||||||
|
using Google.Protobuf.WellKnownTypes;
|
||||||
|
using Grpc.Core;
|
||||||
|
using Grpc.Core.Interceptors;
|
||||||
|
using Grpc.Net.Client;
|
||||||
|
using HelloShop.BasketService.Protos;
|
||||||
|
|
||||||
|
namespace HelloShop.BasketService.FunctionalTests
|
||||||
|
{
|
||||||
|
public class BasketServiceIntegrationTest
|
||||||
|
{
|
||||||
|
private readonly Basket.BasketClient _client;
|
||||||
|
|
||||||
|
public BasketServiceIntegrationTest()
|
||||||
|
{
|
||||||
|
GrpcChannel channel = GrpcChannel.ForAddress(GrpcConstants.GrpcAddress);
|
||||||
|
CallInvoker invoker = channel.Intercept(new AuthenticatedInterceptor());
|
||||||
|
_client = new Basket.BasketClient(invoker);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetBasketReturnsBasket()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var request = new Empty();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var reply = await _client.GetBasketAsync(request);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task UpdateBasketReturnsBasketResponse()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var request = new UpdateBasketRequest
|
||||||
|
{
|
||||||
|
Items =
|
||||||
|
{
|
||||||
|
new BasketListItem { ProductId = 1, Quantity = 2 },
|
||||||
|
new BasketListItem { ProductId = 2, Quantity = 3 }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var reply = await _client.UpdateBasketAsync(request);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(2, reply.Items.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task DeleteBasketReturnsEmpty()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var request = new Empty();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var reply = await _client.DeleteBasketAsync(request);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(reply);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
// Copyright (c) HelloShop Corporation. All rights reserved.
|
||||||
|
// See the license file in the project root for more information.
|
||||||
|
|
||||||
|
using Grpc.Net.Client;
|
||||||
|
using HelloShop.BasketService.Protos;
|
||||||
|
|
||||||
|
namespace HelloShop.BasketService.FunctionalTests
|
||||||
|
{
|
||||||
|
public class GreeterServiceIntegrationTest
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public async Task SayHelloReturnsHelloMessage()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
using var channel = GrpcChannel.ForAddress(GrpcConstants.GrpcAddress);
|
||||||
|
var client = new Greeter.GreeterClient(channel);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var reply = await client.SayHelloAsync(new HelloRequest { Name = "Greeter" });
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal("Hello Greeter", reply.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
// Copyright (c) HelloShop Corporation. All rights reserved.
|
||||||
|
// See the license file in the project root for more information.
|
||||||
|
|
||||||
|
namespace HelloShop.BasketService.FunctionalTests
|
||||||
|
{
|
||||||
|
internal class GrpcConstants
|
||||||
|
{
|
||||||
|
public const string GrpcAddress = "http://localhost:8004";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
<IsTestProject>true</IsTestProject>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="coverlet.collector" Version="6.0.0" />
|
||||||
|
<PackageReference Include="Google.Protobuf" Version="3.21.5" />
|
||||||
|
<PackageReference Include="Grpc.Net.ClientFactory" Version="2.49.0" />
|
||||||
|
<PackageReference Include="Grpc.Tools" Version="2.49.0">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Grpc.JsonTranscoding" Version="8.0.7" />
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
|
||||||
|
<PackageReference Include="xunit" Version="2.5.3" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Protobuf Include="..\..\src\HelloShop.BasketService\Protos\basket.proto" GrpcServices="Client">
|
||||||
|
<Link>Protos\basket.proto</Link>
|
||||||
|
</Protobuf>
|
||||||
|
<Protobuf Include="..\..\src\HelloShop.BasketService\Protos\greet.proto" GrpcServices="Client">
|
||||||
|
<Link>Protos\greet.proto</Link>
|
||||||
|
</Protobuf>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Using Include="Xunit" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
@ -0,0 +1,46 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
<IsTestProject>true</IsTestProject>
|
||||||
|
<IncludeHttpRuleProtos>true</IncludeHttpRuleProtos>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="coverlet.collector" Version="6.0.2">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Google.Protobuf" Version="3.27.2" />
|
||||||
|
<PackageReference Include="Grpc.Net.ClientFactory" Version="2.63.0" />
|
||||||
|
<PackageReference Include="Grpc.Tools" Version="2.64.0">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Grpc.JsonTranscoding" Version="8.0.7" />
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
|
||||||
|
<PackageReference Include="xunit" Version="2.9.0" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Protobuf Include="..\..\src\HelloShop.BasketService\Protos\basket.proto" GrpcServices="Client">
|
||||||
|
<Link>Protos\basket.proto</Link>
|
||||||
|
</Protobuf>
|
||||||
|
<Protobuf Include="..\..\src\HelloShop.BasketService\Protos\greet.proto" GrpcServices="Client">
|
||||||
|
<Link>Protos\greet.proto</Link>
|
||||||
|
</Protobuf>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Using Include="Xunit" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
@ -0,0 +1,34 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
<IsTestProject>true</IsTestProject>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="coverlet.collector" Version="6.0.2">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
|
||||||
|
<PackageReference Include="Moq" Version="4.20.70" />
|
||||||
|
<PackageReference Include="xunit" Version="2.9.0" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\src\HelloShop.BasketService\HelloShop.BasketService.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Using Include="Xunit" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
@ -0,0 +1,71 @@
|
|||||||
|
// Copyright (c) HelloShop Corporation. All rights reserved.
|
||||||
|
// See the license file in the project root for more information.
|
||||||
|
|
||||||
|
using Grpc.Core;
|
||||||
|
|
||||||
|
namespace HelloShop.BasketService.UnitTests.Helpers
|
||||||
|
{
|
||||||
|
public class TestServerCallContext : ServerCallContext
|
||||||
|
{
|
||||||
|
private readonly Metadata _requestHeaders;
|
||||||
|
|
||||||
|
private readonly CancellationToken _cancellationToken;
|
||||||
|
|
||||||
|
private readonly Metadata _responseTrailers;
|
||||||
|
|
||||||
|
private readonly AuthContext _authContext;
|
||||||
|
|
||||||
|
private readonly Dictionary<object, object> _userState;
|
||||||
|
|
||||||
|
private WriteOptions? _writeOptions;
|
||||||
|
|
||||||
|
public Metadata? ResponseHeaders { get; private set; }
|
||||||
|
|
||||||
|
private TestServerCallContext(Metadata requestHeaders, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
_requestHeaders = requestHeaders;
|
||||||
|
_cancellationToken = cancellationToken;
|
||||||
|
_responseTrailers = [];
|
||||||
|
_authContext = new AuthContext(string.Empty, []);
|
||||||
|
_userState = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string MethodCore => "MethodName";
|
||||||
|
|
||||||
|
protected override string HostCore => "HostName";
|
||||||
|
|
||||||
|
protected override string PeerCore => "PeerName";
|
||||||
|
|
||||||
|
protected override DateTime DeadlineCore { get; }
|
||||||
|
|
||||||
|
protected override Metadata RequestHeadersCore => _requestHeaders;
|
||||||
|
|
||||||
|
protected override CancellationToken CancellationTokenCore => _cancellationToken;
|
||||||
|
|
||||||
|
protected override Metadata ResponseTrailersCore => _responseTrailers;
|
||||||
|
|
||||||
|
protected override Status StatusCore { get; set; }
|
||||||
|
|
||||||
|
protected override WriteOptions? WriteOptionsCore { get => _writeOptions; set { _writeOptions = value; } }
|
||||||
|
|
||||||
|
protected override AuthContext AuthContextCore => _authContext;
|
||||||
|
|
||||||
|
protected override ContextPropagationToken CreatePropagationTokenCore(ContextPropagationOptions? options) => throw new NotImplementedException();
|
||||||
|
|
||||||
|
protected override Task WriteResponseHeadersAsyncCore(Metadata responseHeaders)
|
||||||
|
{
|
||||||
|
if (ResponseHeaders != null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Response headers have already been written.");
|
||||||
|
}
|
||||||
|
|
||||||
|
ResponseHeaders = responseHeaders;
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override IDictionary<object, object> UserStateCore => _userState;
|
||||||
|
|
||||||
|
public static TestServerCallContext Create(Metadata? requestHeaders = null, CancellationToken cancellationToken = default) => new(requestHeaders ?? [], cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,133 @@
|
|||||||
|
// Copyright (c) HelloShop Corporation. All rights reserved.
|
||||||
|
// See the license file in the project root for more information.
|
||||||
|
|
||||||
|
using AutoMapper;
|
||||||
|
using Google.Protobuf.WellKnownTypes;
|
||||||
|
using HelloShop.BasketService.AutoMapper;
|
||||||
|
using HelloShop.BasketService.Entities;
|
||||||
|
using HelloShop.BasketService.Protos;
|
||||||
|
using HelloShop.BasketService.Repositories;
|
||||||
|
using HelloShop.BasketService.Services;
|
||||||
|
using HelloShop.BasketService.UnitTests.Helpers;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.Extensions.Logging.Abstractions;
|
||||||
|
using Moq;
|
||||||
|
using System.Security.Claims;
|
||||||
|
|
||||||
|
namespace HelloShop.BasketService.UnitTests.Services
|
||||||
|
{
|
||||||
|
public class BasketServiceTest
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public async Task GetBasketReturnsEmptyForNoUser()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var basketRepositoryMock = new Mock<IBasketRepository>();
|
||||||
|
var loggerMock = NullLogger<CustomerBasketService>.Instance;
|
||||||
|
var mapperMock = new Mock<IMapper>();
|
||||||
|
var service = new CustomerBasketService(basketRepositoryMock.Object, loggerMock, mapperMock.Object);
|
||||||
|
|
||||||
|
TestServerCallContext serverCallContext = TestServerCallContext.Create();
|
||||||
|
|
||||||
|
var httpContext = new DefaultHttpContext
|
||||||
|
{
|
||||||
|
User = new ClaimsPrincipal(new ClaimsIdentity([new Claim(ClaimTypes.NameIdentifier, "1")]))
|
||||||
|
};
|
||||||
|
|
||||||
|
serverCallContext.UserState["__HttpContext"] = httpContext;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
CustomerBasketResponse result = await service.GetBasket(new Empty(), serverCallContext);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Empty(result.Items);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetBasketReturnsItemsForValidUserId()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var basketRepositoryMock = new Mock<IBasketRepository>();
|
||||||
|
basketRepositoryMock.Setup(x => x.GetBasketAsync(It.IsAny<int>(), It.IsAny<CancellationToken>())).ReturnsAsync(new CustomerBasket() { BuyerId = 1, Items = [new BasketItem { ProductId = 1, Quantity = 1 }] });
|
||||||
|
|
||||||
|
var logger = NullLogger<CustomerBasketService>.Instance;
|
||||||
|
|
||||||
|
var mapper = new Mapper(new MapperConfiguration(cfg => cfg.AddProfile<BasketsMapConfiguration>()));
|
||||||
|
|
||||||
|
var service = new CustomerBasketService(basketRepositoryMock.Object, logger, mapper);
|
||||||
|
|
||||||
|
TestServerCallContext serverCallContext = TestServerCallContext.Create();
|
||||||
|
|
||||||
|
HttpContext httpContext = new DefaultHttpContext
|
||||||
|
{
|
||||||
|
User = new ClaimsPrincipal(new ClaimsIdentity([new Claim(ClaimTypes.NameIdentifier, "1")]))
|
||||||
|
};
|
||||||
|
|
||||||
|
serverCallContext.UserState["__HttpContext"] = httpContext;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
CustomerBasketResponse result = await service.GetBasket(new Empty(), serverCallContext);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotEmpty(result.Items);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task UpdateBasketReturnsCustomerBasketResponse()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var basketRepositoryMock = new Mock<IBasketRepository>();
|
||||||
|
basketRepositoryMock.Setup(x => x.UpdateBasketAsync(It.IsAny<CustomerBasket>(), It.IsAny<CancellationToken>())).ReturnsAsync((CustomerBasket basket, CancellationToken token) => basket);
|
||||||
|
|
||||||
|
var logger = NullLogger<CustomerBasketService>.Instance;
|
||||||
|
var mapper = new Mapper(new MapperConfiguration(cfg => cfg.AddProfile<BasketsMapConfiguration>()));
|
||||||
|
|
||||||
|
var service = new CustomerBasketService(basketRepositoryMock.Object, logger, mapper);
|
||||||
|
|
||||||
|
TestServerCallContext serverCallContext = TestServerCallContext.Create();
|
||||||
|
|
||||||
|
HttpContext httpContext = new DefaultHttpContext
|
||||||
|
{
|
||||||
|
User = new ClaimsPrincipal(new ClaimsIdentity([new Claim(ClaimTypes.NameIdentifier, "1")]))
|
||||||
|
};
|
||||||
|
|
||||||
|
serverCallContext.UserState["__HttpContext"] = httpContext;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
UpdateBasketRequest updateBasketRequest = new()
|
||||||
|
{
|
||||||
|
Items = { new BasketListItem { ProductId = 1, Quantity = 1 }, new BasketListItem { ProductId = 2, Quantity = 2 } }
|
||||||
|
};
|
||||||
|
|
||||||
|
CustomerBasketResponse result = await service.UpdateBasket(updateBasketRequest, serverCallContext);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Collection(result.Items, item => Assert.Equal(1, item.ProductId), item => Assert.Equal(2, item.ProductId));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task DeleteBasketReturnsEmpty()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var basketRepositoryMock = new Mock<IBasketRepository>();
|
||||||
|
var logger = NullLogger<CustomerBasketService>.Instance;
|
||||||
|
var mapper = new Mapper(new MapperConfiguration(cfg => cfg.AddProfile<BasketsMapConfiguration>()));
|
||||||
|
var service = new CustomerBasketService(basketRepositoryMock.Object, logger, mapper);
|
||||||
|
|
||||||
|
TestServerCallContext serverCallContext = TestServerCallContext.Create();
|
||||||
|
|
||||||
|
HttpContext httpContext = new DefaultHttpContext
|
||||||
|
{
|
||||||
|
User = new ClaimsPrincipal(new ClaimsIdentity([new Claim(ClaimTypes.NameIdentifier, "1")]))
|
||||||
|
};
|
||||||
|
|
||||||
|
serverCallContext.UserState["__HttpContext"] = httpContext;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
Empty result = await service.DeleteBasket(new Empty(), serverCallContext);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
// Copyright (c) HelloShop Corporation. All rights reserved.
|
||||||
|
// See the license file in the project root for more information.
|
||||||
|
|
||||||
|
using HelloShop.BasketService.Protos;
|
||||||
|
using HelloShop.BasketService.Services;
|
||||||
|
using HelloShop.BasketService.UnitTests.Helpers;
|
||||||
|
|
||||||
|
namespace HelloShop.BasketService.UnitTests.Services
|
||||||
|
{
|
||||||
|
public class GreeterServiceTest
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public async Task SayHelloReturnsCorrectMessage()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var service = new GreeterService();
|
||||||
|
var request = new HelloRequest { Name = "World" };
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await service.SayHello(request, TestServerCallContext.Create());
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal("Hello World", response.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user