409 lines
10 KiB
C#
409 lines
10 KiB
C#
namespace StellaOps.Microservice.Tests;
|
|
|
|
/// <summary>
|
|
/// Unit tests for <see cref="HeaderCollection"/>.
|
|
/// </summary>
|
|
public sealed class HeaderCollectionTests
|
|
{
|
|
#region Constructor Tests
|
|
|
|
[Trait("Category", TestCategories.Unit)]
|
|
[Fact]
|
|
public void Constructor_Default_CreatesEmptyCollection()
|
|
{
|
|
// Arrange & Act
|
|
var headers = new HeaderCollection();
|
|
|
|
// Assert
|
|
headers.Should().BeEmpty();
|
|
}
|
|
|
|
[Trait("Category", TestCategories.Unit)]
|
|
[Fact]
|
|
public void Constructor_WithKeyValuePairs_AddsAllHeaders()
|
|
{
|
|
// Arrange
|
|
var pairs = new[]
|
|
{
|
|
new KeyValuePair<string, string>("Content-Type", "application/json"),
|
|
new KeyValuePair<string, string>("Accept", "application/json")
|
|
};
|
|
|
|
// Act
|
|
var headers = new HeaderCollection(pairs);
|
|
|
|
// Assert
|
|
headers["Content-Type"].Should().Be("application/json");
|
|
headers["Accept"].Should().Be("application/json");
|
|
}
|
|
|
|
[Trait("Category", TestCategories.Unit)]
|
|
[Fact]
|
|
public void Constructor_WithDuplicateKeys_AddsMultipleValues()
|
|
{
|
|
// Arrange
|
|
var pairs = new[]
|
|
{
|
|
new KeyValuePair<string, string>("Accept", "application/json"),
|
|
new KeyValuePair<string, string>("Accept", "text/plain")
|
|
};
|
|
|
|
// Act
|
|
var headers = new HeaderCollection(pairs);
|
|
|
|
// Assert
|
|
headers.GetValues("Accept").Should().BeEquivalentTo(["application/json", "text/plain"]);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Empty Tests
|
|
|
|
[Trait("Category", TestCategories.Unit)]
|
|
[Fact]
|
|
public void Empty_IsSharedInstance()
|
|
{
|
|
// Arrange & Act
|
|
var empty1 = HeaderCollection.Empty;
|
|
var empty2 = HeaderCollection.Empty;
|
|
|
|
// Assert
|
|
empty1.Should().BeSameAs(empty2);
|
|
}
|
|
|
|
[Trait("Category", TestCategories.Unit)]
|
|
[Fact]
|
|
public void Empty_HasNoHeaders()
|
|
{
|
|
// Arrange & Act
|
|
var empty = HeaderCollection.Empty;
|
|
|
|
// Assert
|
|
empty.Should().BeEmpty();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Indexer Tests
|
|
|
|
[Trait("Category", TestCategories.Unit)]
|
|
[Fact]
|
|
public void Indexer_ExistingKey_ReturnsFirstValue()
|
|
{
|
|
// Arrange
|
|
var headers = new HeaderCollection();
|
|
headers.Add("Content-Type", "application/json");
|
|
|
|
// Act
|
|
var value = headers["Content-Type"];
|
|
|
|
// Assert
|
|
value.Should().Be("application/json");
|
|
}
|
|
|
|
[Trait("Category", TestCategories.Unit)]
|
|
[Fact]
|
|
public void Indexer_MultipleValues_ReturnsFirstValue()
|
|
{
|
|
// Arrange
|
|
var headers = new HeaderCollection();
|
|
headers.Add("Accept", "application/json");
|
|
headers.Add("Accept", "text/plain");
|
|
|
|
// Act
|
|
var value = headers["Accept"];
|
|
|
|
// Assert
|
|
value.Should().Be("application/json");
|
|
}
|
|
|
|
[Trait("Category", TestCategories.Unit)]
|
|
[Fact]
|
|
public void Indexer_NonexistentKey_ReturnsNull()
|
|
{
|
|
// Arrange
|
|
var headers = new HeaderCollection();
|
|
|
|
// Act
|
|
var value = headers["X-Missing"];
|
|
|
|
// Assert
|
|
value.Should().BeNull();
|
|
}
|
|
|
|
[Trait("Category", TestCategories.Unit)]
|
|
[Fact]
|
|
public void Indexer_IsCaseInsensitive()
|
|
{
|
|
// Arrange
|
|
var headers = new HeaderCollection();
|
|
headers.Add("Content-Type", "application/json");
|
|
|
|
// Act & Assert
|
|
headers["content-type"].Should().Be("application/json");
|
|
headers["CONTENT-TYPE"].Should().Be("application/json");
|
|
headers["Content-TYPE"].Should().Be("application/json");
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Add Tests
|
|
|
|
[Trait("Category", TestCategories.Unit)]
|
|
[Fact]
|
|
public void Add_NewKey_AddsHeader()
|
|
{
|
|
// Arrange
|
|
var headers = new HeaderCollection();
|
|
|
|
// Act
|
|
headers.Add("Content-Type", "application/json");
|
|
|
|
// Assert
|
|
headers["Content-Type"].Should().Be("application/json");
|
|
}
|
|
|
|
[Trait("Category", TestCategories.Unit)]
|
|
[Fact]
|
|
public void Add_ExistingKey_AppendsValue()
|
|
{
|
|
// Arrange
|
|
var headers = new HeaderCollection();
|
|
headers.Add("Accept", "application/json");
|
|
|
|
// Act
|
|
headers.Add("Accept", "text/plain");
|
|
|
|
// Assert
|
|
headers.GetValues("Accept").Should().HaveCount(2);
|
|
}
|
|
|
|
[Trait("Category", TestCategories.Unit)]
|
|
[Fact]
|
|
public void Add_CaseInsensitiveKey_AppendsToExisting()
|
|
{
|
|
// Arrange
|
|
var headers = new HeaderCollection();
|
|
headers.Add("Content-Type", "application/json");
|
|
|
|
// Act
|
|
headers.Add("content-type", "text/plain");
|
|
|
|
// Assert
|
|
headers.GetValues("Content-Type").Should().HaveCount(2);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Set Tests
|
|
|
|
[Trait("Category", TestCategories.Unit)]
|
|
[Fact]
|
|
public void Set_NewKey_AddsHeader()
|
|
{
|
|
// Arrange
|
|
var headers = new HeaderCollection();
|
|
|
|
// Act
|
|
headers.Set("Content-Type", "application/json");
|
|
|
|
// Assert
|
|
headers["Content-Type"].Should().Be("application/json");
|
|
}
|
|
|
|
[Trait("Category", TestCategories.Unit)]
|
|
[Fact]
|
|
public void Set_ExistingKey_ReplacesValue()
|
|
{
|
|
// Arrange
|
|
var headers = new HeaderCollection();
|
|
headers.Add("Content-Type", "text/plain");
|
|
headers.Add("Content-Type", "text/html");
|
|
|
|
// Act
|
|
headers.Set("Content-Type", "application/json");
|
|
|
|
// Assert
|
|
headers.GetValues("Content-Type").Should().BeEquivalentTo(["application/json"]);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GetValues Tests
|
|
|
|
[Trait("Category", TestCategories.Unit)]
|
|
[Fact]
|
|
public void GetValues_ExistingKey_ReturnsAllValues()
|
|
{
|
|
// Arrange
|
|
var headers = new HeaderCollection();
|
|
headers.Add("Accept", "application/json");
|
|
headers.Add("Accept", "text/plain");
|
|
headers.Add("Accept", "text/html");
|
|
|
|
// Act
|
|
var values = headers.GetValues("Accept");
|
|
|
|
// Assert
|
|
values.Should().BeEquivalentTo(["application/json", "text/plain", "text/html"]);
|
|
}
|
|
|
|
[Trait("Category", TestCategories.Unit)]
|
|
[Fact]
|
|
public void GetValues_NonexistentKey_ReturnsEmptyEnumerable()
|
|
{
|
|
// Arrange
|
|
var headers = new HeaderCollection();
|
|
|
|
// Act
|
|
var values = headers.GetValues("X-Missing");
|
|
|
|
// Assert
|
|
values.Should().BeEmpty();
|
|
}
|
|
|
|
[Trait("Category", TestCategories.Unit)]
|
|
[Fact]
|
|
public void GetValues_IsCaseInsensitive()
|
|
{
|
|
// Arrange
|
|
var headers = new HeaderCollection();
|
|
headers.Add("Accept", "application/json");
|
|
|
|
// Act & Assert
|
|
headers.GetValues("accept").Should().Contain("application/json");
|
|
headers.GetValues("ACCEPT").Should().Contain("application/json");
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region TryGetValue Tests
|
|
|
|
[Trait("Category", TestCategories.Unit)]
|
|
[Fact]
|
|
public void TryGetValue_ExistingKey_ReturnsTrueAndValue()
|
|
{
|
|
// Arrange
|
|
var headers = new HeaderCollection();
|
|
headers.Add("Content-Type", "application/json");
|
|
|
|
// Act
|
|
var result = headers.TryGetValue("Content-Type", out var value);
|
|
|
|
// Assert
|
|
result.Should().BeTrue();
|
|
value.Should().Be("application/json");
|
|
}
|
|
|
|
[Trait("Category", TestCategories.Unit)]
|
|
[Fact]
|
|
public void TryGetValue_NonexistentKey_ReturnsFalse()
|
|
{
|
|
// Arrange
|
|
var headers = new HeaderCollection();
|
|
|
|
// Act
|
|
var result = headers.TryGetValue("X-Missing", out var value);
|
|
|
|
// Assert
|
|
result.Should().BeFalse();
|
|
value.Should().BeNull();
|
|
}
|
|
|
|
[Trait("Category", TestCategories.Unit)]
|
|
[Fact]
|
|
public void TryGetValue_IsCaseInsensitive()
|
|
{
|
|
// Arrange
|
|
var headers = new HeaderCollection();
|
|
headers.Add("Content-Type", "application/json");
|
|
|
|
// Act
|
|
var result = headers.TryGetValue("content-type", out var value);
|
|
|
|
// Assert
|
|
result.Should().BeTrue();
|
|
value.Should().Be("application/json");
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ContainsKey Tests
|
|
|
|
[Trait("Category", TestCategories.Unit)]
|
|
[Fact]
|
|
public void ContainsKey_ExistingKey_ReturnsTrue()
|
|
{
|
|
// Arrange
|
|
var headers = new HeaderCollection();
|
|
headers.Add("Content-Type", "application/json");
|
|
|
|
// Act & Assert
|
|
headers.ContainsKey("Content-Type").Should().BeTrue();
|
|
}
|
|
|
|
[Trait("Category", TestCategories.Unit)]
|
|
[Fact]
|
|
public void ContainsKey_NonexistentKey_ReturnsFalse()
|
|
{
|
|
// Arrange
|
|
var headers = new HeaderCollection();
|
|
|
|
// Act & Assert
|
|
headers.ContainsKey("X-Missing").Should().BeFalse();
|
|
}
|
|
|
|
[Trait("Category", TestCategories.Unit)]
|
|
[Fact]
|
|
public void ContainsKey_IsCaseInsensitive()
|
|
{
|
|
// Arrange
|
|
var headers = new HeaderCollection();
|
|
headers.Add("Content-Type", "application/json");
|
|
|
|
// Act & Assert
|
|
headers.ContainsKey("content-type").Should().BeTrue();
|
|
headers.ContainsKey("CONTENT-TYPE").Should().BeTrue();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Enumeration Tests
|
|
|
|
[Trait("Category", TestCategories.Unit)]
|
|
[Fact]
|
|
public void GetEnumerator_EnumeratesAllHeaderValues()
|
|
{
|
|
// Arrange
|
|
var headers = new HeaderCollection();
|
|
headers.Add("Content-Type", "application/json");
|
|
headers.Add("Accept", "text/plain");
|
|
headers.Add("Accept", "text/html");
|
|
|
|
// Act
|
|
var list = headers.ToList();
|
|
|
|
// Assert
|
|
list.Should().HaveCount(3);
|
|
list.Should().Contain(kvp => kvp.Key == "Content-Type" && kvp.Value == "application/json");
|
|
list.Should().Contain(kvp => kvp.Key == "Accept" && kvp.Value == "text/plain");
|
|
list.Should().Contain(kvp => kvp.Key == "Accept" && kvp.Value == "text/html");
|
|
}
|
|
|
|
[Trait("Category", TestCategories.Unit)]
|
|
[Fact]
|
|
public void GetEnumerator_EmptyCollection_EnumeratesNothing()
|
|
{
|
|
// Arrange
|
|
var headers = new HeaderCollection();
|
|
|
|
// Act
|
|
var list = headers.ToList();
|
|
|
|
// Assert
|
|
list.Should().BeEmpty();
|
|
}
|
|
|
|
#endregion
|
|
}
|