测试 gRPC 购物车服务
This commit is contained in:
1 parent
c192d209fd
commit
680ce10fa7
12 files changed
+494
-3
No files matched your search
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user