2010-11-23 12 views
9

Ich entwickle gerade eine asp.net mvc 2 Anwendung, die den Standard SqlMembershipProvider für die Authentifizierung verwendet. Ich habe eine Controller-Methode implementiert, die den ProviderUserKey des aktuellen Benutzers durch Aufrufen von Membership.GetUser().ProviderUserKey liest. Jetzt versuche ich, einige Testmethoden für diesen Controller zu schreiben.Mocking ein MembershipUser

Um der Abhängung auf die statische Membership-Klasse loszuwerden, habe ich eine dünne Hülle geschaffen und mein Controller auf der entsprechenden Schnittstelle abhängig:

public interface IStaticMembershipService { 
    MembershipUser GetUser(); 

    void UpdateUser(MembershipUser user); 
} 

Bisher funktioniert alles, aber um Einheit -test den Controller, ich muss immer noch die GetUser() Methode dieser Schnittstelle mock und ein MembershipUser-Objekt zurückgeben, das eine ProviderUserKey-Eigenschaft enthält. Was ist der einfachste Weg, ein solches Objekt zu verspotten?

Ich benutze Moq als Spott Framework.

Antwort

11

es so etwas wie folgt aussehen würde:

var membershipMock = new Mock<IStaticMembershipService>(); 
var userMock = new Mock<MembershipUser>(); 
userMock.Setup(u => u.ProviderUserKey).Returns(guid); 
membershipMock.Setup(s => s.GetUser()).Returns(userMock.Object); 

Wenn die MembershipUser Klasse selbst ist nicht leihen spott (dh wenn ProviderUserKey nicht virtuell), möchten Sie Ihr eigenes Objekt erstellen, um die Werte darzustellen, die Sie von einem MembershipUser-Objekt benötigen, und lassen Sie Ihren Dienst stattdessen einen dieser Werte zurückgeben.

Es gibt auch eine geringe Möglichkeit, dass ein MembershipUser ein poco artiges Objekt ist, und Sie können eine Instanz wie folgt erstellen:

var userMock = new MembershipUser {ProviderUserKey = guid}; 
+0

Vielen Dank, erstellen Sie ein Mock der MembershipUser-Klasse funktioniert super. – Simon

1

Etwas ähnliches wie folgt aus:

var user = new MembershipUser(); 
var membershipService = new Mock<IStaticMembershipService>(); 
membershipService.Setup(p => p.GetUser()).Returns(user); 
2

Ich glaube, Sie benötigen, um Ihre Implementierung Besonderheiten von der Schnittstelle wirklich die Verbraucher trennen kümmert sich um. Ich bin mir nicht sicher, wofür die Steuerung den ProviderUserKey benötigt, wenn er in eine bestimmte Klasse umgewandelt wird, etc., aber ich würde darauf achten, dass Ihre Schnittstelle die Anforderungen des Controllers erfüllt und nicht umgekehrt. So etwas wie (ohne weitere Einzelheiten zu kennen):

public interface IMembershipDetailsService { 
    Guid UserKey { get; } 
} 

Sobald Sie diese Abstraktionsebene zu tun, dann spöttisch wird viel einfacher, weil Sie gerade tun könnte:

membershipService.Setup (svc => svc.UserKey).Returns (myGuid); 

Nur ein weiterer Gedanke, anstatt zu versuchen, Um ein ganzes MembershipUser-Objekt zurückzugeben, müssen Sie einen weiteren Stub ausführen.

+0

+1 Sehr guter Punkt. – StriplingWarrior

0

Könnten Sie etwas wie unten tun, wenn Sie die HttpContext Zeug auch verdecken müssen .. unten ist NUnit und Moq.

[SetUp] 
private void Setup() 
{ 
    _mockHttpContext = new Mock<HttpContextBase>(); 
    _mockStaticMembership = new Mock<IStaticMembershipService>();   
    _mockUser = new Mock<MembershipUser>(); 
    _mockPrincipalUser = new Mock<IPrincipal>();   

    _mockHttpContext.Setup(http => http.User).Returns(_mockPrincipalUser.Object); 
    _mockPrincipalUser.Setup(principal => principal.Identity.Name).Returns("myname"); 
    _mockUser.Setup(user => user.ProviderUserKey).Returns(Guid.NewGuid()); 

    _mockStaticMembership.Setup(membership => membership.GetUser(It.IsAny<string>())).Returns(_mockUser.Object); 

} 

[Test] 
public void Some_Test_For_My_Controller() 
{    
    var controller = new MyController(_mockStaticMembership.Object);    
    controller.ControllerContext = new ControllerContext(_mockHttpContext.Object, new RouteData(), controller); 

    //Test your action and verify 
}