使用最小起订量

时间:2019-03-17 11:15:02

标签: c# unit-testing moq extension-methods

我有如下两种扩展方法,

public static string FindFirstValue(this ClaimsPrincipal principal, string claimType, bool throwIfNotFound = false)
{
    string value = principal.FindFirst(claimType)?.Value;
    if (throwIfNotFound && string.IsNullOrWhiteSpace(value))
    {
        throw new InvalidOperationException(
            string.Format(CultureInfo.InvariantCulture, "The supplied principal does not contain a claim of type {0}", claimType));
    }

    return value;
}

public static string GetObjectIdentifierValue(this ClaimsPrincipal principal, bool throwIfNotFound = true)
{
    return principal.FindFirstValue("http://schemas.microsoft.com/identity/claims/objectidentifier", throwIfNotFound);
}

我听说不可能对扩展方法进行单元测试,因为它们是静态的。 只是想检查是否有人想使用Moq对上述扩展方法进行单元测试?

有人能指出我正确的方向吗?

2 个答案:

答案 0 :(得分:2)

  

我听说不可能对扩展方法进行单元测试,因为它们   是静态的。

通常不是这样。如果静态方法依赖于创建其体内的依赖项,并且 对于特定的输入将获得特定的输出,则可以肯定地对其进行单元测试。

根据您的情况,可以避免使用Moq对这些扩展方法进行单元测试。您可以创建ClaimsPrincipal的实例,并使用这些实例测试扩展方法。在下面,您将找到一些示例:

[Test]
public void WhenClaimTypeIsMissingAndAvoidExceptions_FindFirstValue_Returns_Null()
{
    var principal = new ClaimsPrincipal();

    var value = principal.FindFirstValue("claim type value");

    Assert.IsNull(value);
}

[Test]
public void WhenClaimTypeIsMissingAndThrowExceptions_FindFirstValue_ThrowsException()
{
    var principal = new ClaimsPrincipal();

    var claimType = "claim type value";

    Assert.Throws(Is.TypeOf<InvalidOperationException>()
                    .And.Message.EqualTo($"The supplied principal does not contain a claim of type {claimType}")
                , () => principal.FindFirstValue(claimType, throwIfNotFound: true));
}

[Test]
public void WhenClaimTypeIsFound_FindFirstValue_ReturnsTheValue()
{
    var principal = new ClaimsPrincipal();
    principal.AddIdentity(new ClaimsIdentity(new List<Claim> {new Claim("type", "1234")}));

    var value = principal.FindFirstValue("type");

    Assert.AreEqual(value,"1234");
 }

答案 1 :(得分:1)

您的扩展方法是FindFirst的包装,因此这实际上是您要模拟的方法。您很幸运:),因为ClaimPrincipal.FindFirstvirtual方法,可以模拟它。

//Arrange
var principal = new Mock<ClaimsPrincipal>();
principal
    .Setup(m => m.FindFirst(It.IsAny<string>()))
    .Returns(new Claim("name", "John Doe"));

//Act
string value = principal.Object.FindFirstValue("claimType", true);

//Assert
Assert.AreEqual("John Doe", value);