47

I'm working with a ASP.NET MVC solution in a test driven manner and I want to login a user to my application using forms authentication. The code I would like to end up with in the controller looks something like this:

FormsAuthentication.SetAuthCookie(userName, false);

My question is how do I write a test to justify this code?

Is there a way to check that the SetAuthCookie method was called with the correct parameters?

Is there any way of injecting a fake/mock FormsAuthentication?

maz
  • 2,466
  • 1
  • 25
  • 32

1 Answers1

68

I would start by writing an interface and a wrapper class that will encapsulate this logic and then use the interface in my controller:

public interface IAuth 
{
    void DoAuth(string userName, bool remember);
}

public class FormsAuthWrapper : IAuth 
{
    public void DoAuth(string userName, bool remember) 
    {
        FormsAuthentication.SetAuthCookie(userName, remember);
    }
}

public class MyController : Controller 
{
    private readonly IAuth _auth;

    public MyController(IAuth auth) 
    {
        _auth = auth;
    }

}

Now IAuth could be easily mocked in a unit test and verify that the controller calls the expected methods on it. I would NOT unit test the FormsAuthWrapper class because it just delegates the call to the FormsAuthentication which does what it is supposed to do (Microsoft guarantee :-)).

ken2k
  • 48,145
  • 10
  • 116
  • 176
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • 2
    +1 on this, don't test other people's frameworks, just YOUR usage of THEM. We do the same (similar) thing in our app (wrap FormsAuth stuff, etc) – chadmyers Dec 14 '08 at 16:16
  • 18
    *sigh* Microsoft is so proud of this framework being SO testable! I was hoping there was some built in way to mock this without wrapping. Guess not :( – maz Dec 14 '08 at 19:39
  • 6
    The problem is not that the framework is not testable...the problem is that the FormsAuthentication class predates the unit-testing-design of MVC. As Darin has mentioned the best way to address this is to decouple the controller from the class with the static methods using an interface. – Jesse Jan 28 '12 at 21:25
  • could you give an example on how you would mock IAuth Darin? – DevDave Feb 24 '12 at 11:55
  • @Tyler, this will depend on what you are trying to unit test actually. – Darin Dimitrov Feb 24 '12 at 11:59
  • I am just testing LogOn and its redirects, it is the standard MVC3 LogOn with minor changes, but it is the FormsAuthentication that is causing the exception in my unit tests. I don't see how the wrapper is doing anything else as it also calls FormsAuthentication – DevDave Feb 24 '12 at 12:04
  • 1
    @Tyler, you should have your AccountController take an `IAuth` interface at its constructor and no longer use any FormsAuthentication in it. – Darin Dimitrov Feb 24 '12 at 12:11
  • so I could just pass in a bool 'DoNotAuth'? – DevDave Feb 24 '12 at 12:14
  • @Tyler, I don't understand what you mean. Please ask a new question, show your code so far and explain what you are trying to achieve. – Darin Dimitrov Feb 24 '12 at 12:16