我有一个方法来使用IHttpContextAccessor获取标头值
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. ‘
解决方法
您可以使用DefaultHttpContext作为IHttpContextAccessor.HttpContext的支持.节省您必须设置太多东西
接下来,您不能使用It.IsAny< string>()作为返回结果.它们仅用于设置表达式.
检查重构器
[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>>(); }
Class In Test也可能存在问题,因为它应该在实际显式注入时手动初始化HeaderConfiguration.
public Book(IHeaderConfiguration headerConfiguration,IHttpContextAccessor httpContextAccessor) { _httpContextAccessor = httpContextAccessor; _tenantID = headerConfiguration.GetTenantId(_httpContextAccessor); }