2017-01-17 1 views
0

Beim Ausführen meiner Komponententestmethode erhalte ich FormsAuthentication.SignOut() Fehler. Ich habe die Httpcontext ähnlicheThrowing-Fehler in Komponententest FormsAuthentication.SignOut()

verspotteten
var httpRequest = new HttpRequest("", "http://localhost/", ""); 
var stringWriter = new StringWriter(); 
var httpResponse = new HttpResponse(stringWriter); 
var httpContext = new HttpContext(httpRequest, httpResponse); 
var sessionContainer = new HttpSessionStateContainer(
    "id", 
    new SessionStateItemCollection(), 
    new HttpStaticObjectsCollection(), 
    10, 
    true, 
    HttpCookieMode.AutoDetect, 
    SessionStateMode.InProc, 
    false); 
SessionStateUtility.AddHttpSessionStateToContext(httpContext, sessionContainer); 
var controller = new AccountController(); 
var requestContext = new RequestContext(new HttpContextWrapper(httpContext), new RouteData()); 
controller.ControllerContext = new ControllerContext(requestContext, controller); 
var actual = controller.Login(new CutomerModel() { Login = "admin", Password = "Password1" }); 
return httpContext; 

im Login-Methode

public ActionResult Login(CutomerModel obj) 
{ 
    FormsAuthentication.SignOut(); 
} 

FormsAuthentication.SignOut(); wirft

‚Objektverweis auf eine Instanz eines Objekts nicht gesetzt. "

Antwort

1

Die statische Methode FormsAuthentication.SignOut ist abhängig von anderen statischen Element HttpContext.Current, die während der Tests Einheit nicht zur Verfügung steht. Schließen Sie Ihre Controller fest an HttpContext.Current an, was statisch ist, was zu einem Code führt, der sehr schwierig zu testen ist. Versuchen Sie, eine Kopplung mit statischen Aufrufen zu vermeiden.

Seitennotiz: Wenn Sie Schwierigkeiten beim Einrichten eines Komponententests für Ihren Code haben, ist dies ein sicheres Zeichen dafür, dass er überprüft und höchstwahrscheinlich umstrukturiert werden muss.

Abstract FormsAuthentication ruft in ihre eigenen Interessen/Schnittstellen, so dass sie verspottet werden können.

public interface IFormsAuthenticationService { 

    void SignOut(); 

    //...other code removed for brevity 
} 

Produktionscode könnte den tatsächlichen Anruf wickelt, die als HttpContext.Current arbeiten sollen, ist dann zur Verfügung. Stellen Sie sicher, dass der DI-Container darüber informiert ist, wie die Abhängigkeiten aufgelöst werden.

public class FormsAuthenticationService : IFormsAuthenticationService { 

    public void SignOut() { 
     FormsAuthentication.SignOut(); 
    } 

    //...other code removed for brevity 

} 

Refactor der Controller auf die Abstraktion und nicht die Umsetzung betreffen.

public class AccountController : Controller { 

    //...other code removed for brevity. 

    private readonly IFormsAuthenticationService formsAuthentication; 

    public AccountController(IFormsAuthenticationService formsAuthentication) { 
     //...other arguments removed for brevity 
     this.formsAuthentication = formsAuthentication; 
    } 

    public ActionResult Login(CutomerModel obj) { 
     formsAuthentication.SignOut(); 
     //... 
     return View(); 
    } 

    //...other code removed for brevity. 
} 

Und und Beispieltest

Hinweis: ich Moq für spöttische Abhängigkeiten und FluentAssertions für die Geltendmachung Ergebnisse verwenden.

[TestMethod] 
public void LoginTest() { 
    //Arrange 
    var model = new CutomerModel() { Login = "admin", Password = "Password1" };   
    var mockFormsAuthentication = new Mock<IFormsAuthenticationService>(); 

    var controller = new AccountController(mockFormsAuthentication.Object); 

    //Act 
    var actual = controller.Login(model) as ViewResult; 

    //Assert (using FluentAssertions) 
    actual.Should().NotBeNull(because: "the actual result should have the returned view"); 
    mockFormsAuthentication.Verify(m => m.SignOut(), Times.Once); 
} 
Verwandte Themen