You can use the DefaultHttpContext as a backing for the IHttpContextAccessor.HttpContext. Saves you having to set-up too many things
Next you cannot use It.IsAny<string>() as a Returns result. They were meant to be used in the set up expressions alone.
Check the refactor
[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>>();
}
There may also be an issue with the Class Under Test as it is manually initializing the HeaderConfiguration when it should actually be explicitly injected.
public Book(IHeaderConfiguration headerConfiguration, IHttpContextAccessor httpContextAccessor) {
_httpContextAccessor = httpContextAccessor;
_tenantID = headerConfiguration.GetTenantId(_httpContextAccessor);
}