J'ai une méthode pour obtenir la valeur de l'en-tête en utilisant IHttpContextAccessor
public class HeaderConfiguration : IHeaderConfiguration
{
public HeaderConfiguration()
{
}
public string GetTenantId(IHttpContextAccessor httpContextAccessor)
{
return httpContextAccessor.HttpContext.Request.Headers["Tenant-ID"].ToString();
}
}
Je teste la méthode GetBookByBookId
Disons que la méthode ressemble à ceci:
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
//...
}
}
Voici mon test unitaire pour la méthode 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>>();
}
Mais pour cette ligne:
mockHttpContextAccessor.Setup(req => req.HttpContext.Request.Headers["Tenant-ID"].ToString()).Returns(It.IsAny<string>());
Ça dit
System.NotSupportedException: 'Le type à simuler doit être une interface ou une classe abstraite ou non scellée. "
Je me demandais quelle était la bonne façon de se moquer de IHttpContextAccessor
avec une valeur d'en-tête?
Vous pouvez utiliser le DefaultHttpContext
comme support pour le IHttpContextAccessor.HttpContext
. Vous évite d'avoir à configurer trop de choses
Ensuite, vous ne pouvez pas utiliser It.IsAny<string>()
comme résultat Returns
. Ils étaient destinés à être utilisés uniquement dans les expressions définies.
Vérifiez le 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>>();
}
Il peut également y avoir un problème avec la classe en cours de test car elle initialise manuellement le HeaderConfiguration
alors qu'il doit effectivement être injecté explicitement.
public Book(IHeaderConfiguration headerConfiguration, IHttpContextAccessor httpContextAccessor) {
_httpContextAccessor = httpContextAccessor;
_tenantID = headerConfiguration.GetTenantId(_httpContextAccessor);
}