webentwicklung-frage-antwort-db.com.de

So fügen Sie Ansprüche in einem falschen ClaimsPrincipal hinzu

Ich versuche, meinen Controller-Code zu testen, der die Informationen vom ClaimsPrincipal.Current abruft. Im Controller-Code I

public class HomeController {
    public ActionResult GetName() {
        return Content(ClaimsPrincipal.Current.FindFirst("name").Value);
    }
}

Und ich versuche, meinen ClaimsPrincipal mit Claims zu verspotten, aber ich habe immer noch keinen verspotteten Wert aus dem Claim.

// Arrange
IList<Claim> claimCollection = new List<Claim>
{
    new Claim("name", "John Doe")
};

var identityMock = new Mock<ClaimsIdentity>();
identityMock.Setup(x => x.Claims).Returns(claimCollection);

var cp = new Mock<ClaimsPrincipal>();
cp.Setup(m => m.HasClaim(It.IsAny<string>(), It.IsAny<string>())).Returns(true);
cp.Setup(m => m.Identity).Returns(identityMock.Object);

var sut = new HomeController();

var contextMock = new Mock<HttpContextBase>();
contextMock.Setup(ctx => ctx.User).Returns(cp.Object);

var controllerContextMock = new Mock<ControllerContext>();
controllerContextMock.Setup(con => con.HttpContext).Returns(contextMock.Object);
controllerContextMock.Setup(con => con.HttpContext.User).Returns(cp.Object);

sut.ControllerContext = controllerContextMock.Object;

// Act
var viewresult = sut.GetName() as ContentResult;

// Assert
Assert.That(viewresult.Content, Is.EqualTo("John Doe"));

Der Inhalt von viewresult.Content ist leer, während ich den Komponententest durchführe. Irgendeine Hilfe, wenn ich den Scheinanspruch hinzufügen kann. Vielen Dank.

23
Henry

Zunächst fehlt Ihnen diese Zeile in Ihrem Test:

Thread.CurrentPrincipal = cp.Object;  

(und dann in TearDown aufräumen).

Zweitens ist das Verspotten von Hauptobjekten, wie @trailmax erwähnt, unpraktisch. In deinem Fall, ClaimsPrincipal.FindFirst (laut dekompilierter Quelle) untersucht private Felder seiner Instanz, deshalb hat das Verspotten nicht geholfen.

Ich bevorzuge die Verwendung von zwei einfachen Klassen, die es mir ermöglichen, anspruchsbasierte Funktionen nach Einheiten zu testen:

    public class TestPrincipal : ClaimsPrincipal
    {
        public TestPrincipal(params Claim[] claims) : base(new TestIdentity(claims))
        {
        }
    }

    public class TestIdentity : ClaimsIdentity
    {
        public TestIdentity(params Claim[] claims) : base(claims)
        {
        }
    }

dann schrumpft dein Test auf:

    [Test]
    public void TestGetName()
    {
        // Arrange
        var sut = new HomeController();
        Thread.CurrentPrincipal = new TestPrincipal(new Claim("name", "John Doe"));

        // Act
        var viewresult = sut.GetName() as ContentResult;

        // Assert
        Assert.That(viewresult.Content, Is.EqualTo("John Doe"));
    }

und es vergeht jetzt, ich habe gerade überprüft.

28
felix-b

Sie müssen nicht verspotten ClaimsPrincipal es hat keine externen Abhängigkeiten und Sie können es ohne Verspotten erstellen:

var claims = new List<Claim>() 
{ 
    new Claim(ClaimTypes.Name, "username"),
    new Claim(ClaimTypes.NameIdentifier, "userId"),
    new Claim("name", "John Doe"),
};
var identity = new ClaimsIdentity(claims, "TestAuthType");
var claimsPrincipal = new ClaimsPrincipal(identity);

Und ich bin nicht sicher, was Sie hier testen. "John Doe" wird sicherlich nicht Teil von viewResult.Content weil es noch nie so eingestellt wurde.

54
trailmax