gpt4 book ai didi

c# - 在单元测试中模拟 IHttpContextAccessor

转载 作者:可可西里 更新时间:2023-11-01 07:44:28 32 4
gpt4 key购买 nike

我有一个使用 IHttpContextAccessor 获取 header 值的方法

public class HeaderConfiguration : IHeaderConfiguration
{
public HeaderConfiguration()
{

}

public string GetTenantId(IHttpContextAccessor httpContextAccessor)
{
return httpContextAccessor.HttpContext.Request.Headers["Tenant-ID"].ToString();
}
}

我正在测试 GetBookByBookId 方法

假设该方法如下所示:

public class Book
{
private readonly IHttpContextAccessor _httpContextAccessor;
private IHeaderConfiguration _headerConfiguration;
private string _tenantID;

public Book(IHeaderConfiguration headerConfiguration, IHttpContextAccessor httpContextAccessor){
var headerConfig = new HeaderConfiguration();
_httpContextAccessor = httpContextAccessor;
_tenantID = headerConfig.GetTenantId(_httpContextAccessor);
}

public Task<List<BookModel>> GetBookByBookId(string id){
//do something with the _tenantId
//...
}
}

这是我对 GetBookByBookId 方法的单元测试

[Fact]
public void test_GetBookByBookId()
{
//Arrange

//Mock IHttpContextAccessor
var mockHttpContextAccessor = new Mock<IHttpContextAccessor>();

mockHttpContextAccessor.Setup(req => req.HttpContext.Request.Headers["Tenant-ID"].ToString()).Returns(It.IsAny<string>());
//Mock HeaderConfiguration
var mockHeaderConfiguration = new Mock<IHeaderConfiguration>();
mockHeaderConfiguration.Setup(x => x.GetTenantId(mockHttpContextAccessor.Object)).Returns(It.IsAny<string>());

var book = new Book( mockHttpContextAccessor.Object, mockHeaderConfiguration.Object);

var bookId = "100";

//Act
var result = book.GetBookByBookId(bookId);

//Assert
result.Result.Should().NotBeNull().And.
BeOfType<List<BookModel>>();
}

但是对于这一行:

mockHttpContextAccessor.Setup(req => req.HttpContext.Request.Headers["Tenant-ID"].ToString()).Returns(It.IsAny<string>());

它说

System.NotSupportedException: 'Type to mock must be an interface or an abstract or non-sealed class. '

我想知道用 header 值模拟 IHttpContextAccessor 的正确方法是什么?

最佳答案

您可以使用 DefaultHttpContext作为 IHttpContextAccessor.HttpContext 的支持.省去你设置太多东西的麻烦

接下来你不能使用It.IsAny<string>()作为Returns结果。它们旨在单独用于设置表达式。

检查重构

[Fact]
public async Task test_GetBookByBookId() {
//Arrange

//Mock IHttpContextAccessor
var mockHttpContextAccessor = new Mock<IHttpContextAccessor>();
var context = new DefaultHttpContext();
var fakeTenantId = "abcd";
context.Request.Headers["Tenant-ID"] = fakeTenantId;
mockHttpContextAccessor.Setup(_ => _.HttpContext).Returns(context);
//Mock HeaderConfiguration
var mockHeaderConfiguration = new Mock<IHeaderConfiguration>();
mockHeaderConfiguration
.Setup(_ => _.GetTenantId(It.IsAny<IHttpContextAccessor>()))
.Returns(fakeTenantId);

var book = new Book(mockHttpContextAccessor.Object, mockHeaderConfiguration.Object);

var bookId = "100";

//Act
var result = await book.GetBookByBookId(bookId);

//Assert
result.Should().NotBeNull().And.
BeOfType<List<BookModel>>();
}

被测类也可能存在问题,因为它正在手动初始化 HeaderConfiguration什么时候应该显式注入(inject)。

public Book(IHeaderConfiguration headerConfiguration, IHttpContextAccessor httpContextAccessor) {
_httpContextAccessor = httpContextAccessor;
_tenantID = headerConfiguration.GetTenantId(_httpContextAccessor);
}

关于c# - 在单元测试中模拟 IHttpContextAccessor,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50916969/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com