Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mocking UserPrincipal

Tags:

c#

.net

tdd

I have a class that handles password changes and expiration checks for exchange mailboxes. I check for LastPasswordSet on a UserPrincipal.

Now what about TDD?

I want to check if my class handles the password checks correctly by writing some tests. But I cant get my head around how I could mock the UserPrincipal.FindByIdentity(principalContext, [some username]).

I'm about to write a method that return true/false if the password has been changed the last 90 days. So I would like to mock the UserPrincipal so I can set the LastPasswordSet return value in my tests just to check the logic I'm about to write for the "password needs change notification".

like image 731
Peter Wikström Avatar asked Aug 22 '11 08:08

Peter Wikström


2 Answers

I realize this is an old post, but recently I ran into the same issue as the original poster and after reading the answer, I thought I would have to do the same thing. I don't want someone else to read this post and lose valuable time like I did, so I decided to truly answer this post.

After realizing that there is no easy way to wrap the UserPrincipal functionality nor rely on integration or end-to-end tests like suggested, I remembered there is a way to mock static classes. With that being said, below is exactly how to do it using Telerik JustMock.

private void MockUserPrincipal()
    {
        //Mock principal context
        var context = Mock.Create<PrincipalContext>((action) => action.MockConstructor());

        //Mock user principal
        var user = Mock.Create(() => new UserPrincipal(context));           

        //Mock the properties you need
        Mock.Arrange(() => user.Enabled).Returns(true);
        Mock.Arrange(() => user.UserPrincipalName).Returns("TestUser");
        Mock.Arrange(() => user.LastPasswordSet).Returns(DateTime.Now);

        //Mock any functions you need
        Mock.Arrange(() => user.IsAccountLockedOut()).Returns(false);

        //Setup static UserPrincipal class
        Mock.SetupStatic<UserPrincipal>();

        //Mock the static function you need
        Mock.Arrange(() => UserPrincipal.FindByIdentity(Arg.IsAny<PrincipalContext>(), Arg.AnyString)).Returns(user);  

        //Now calling UserPrincipal.FindByIdentity with any context and identity will return the mocked UserPrincipal
    }
like image 71
csteele Avatar answered Oct 05 '22 10:10

csteele


I'll answer that with the pithy phrase

"Don't mock types you don't own"

couldn't find an authoritative blogpost to back that up. Sample link. Although it seems to be attributed to Joe Walnes.

UserPrincipal if I remember is a .Net framework class related to authentication. Mocking types that are out of your control (can change) can lead to fragile tests.

Instead discover what your design wants from UserPrincipal

  • find the role that UserPrincipal fulfills or implements indirectly via TDDing the clients
  • Mock that role in your unit tests and test all callers.
  • Have "integration tests" to ensure that your real implementation pushes the right buttons on UserPrincipal when invoked.
  • Rely on end-to-end / acceptance tests to find bugs that occur when all components are strung together.
like image 28
Gishu Avatar answered Oct 05 '22 11:10

Gishu