views:

182

answers:

2

ASP.Net app in Visual Studio 2008

I'm creating unit tests to test (in)valid logins for a web app. I have an Authenticate(User,Pass) bool method. The null case and invalid password tests are properly working.

My question is how to test a valid login. I have accounts that are valid for the web app, but I feel like hardcoding in the username and password probably isn't the best solution.

I'm thinking I may have to: create a test user grant the user access to the web app run my tests delete the testuser

Is there a better approach?

A: 

Can't you use a mock data source instead of actual one from where the actual usernames and passwords are retrieved?

That would be my recommended approach since what you want to test is the authentication procedure, not the data.

Bruno Rothgiesser
problem is that the accounts are in Active Directory. I failed to mention that in the question D'oh
Rob
Maybe do a local testing LDAP server?
queen3
+4  A: 

First of all, if you're talking to a real web application or a real database, you're not doing unit testing, you're doing integration testing.

What exactly is it that you're trying to test here?

That:

  • Passing in a wrong username and/or password will not log in the user?
  • Passing in a correct username and/or password will log in the user?
  • That an account really is in Active Directory? What would that prove? That your IT Admin did his/her job?

Remember that you shouldn't be asserting facts, you should be asserting behavior. So instead of trying to verify that a specific account is in AD, verify that when given the correct username and password, your code behaves as expected, and when given a wrong username or password, it also behaves as expected, and you should try to do so without involving Active Directory.

In the first two cases above, there's multiple pieces of code involved:

  • Code that takes in the username and password
  • Code that tries to locate an existing account with that username and password
  • Code that stores the "is now logged in" fact
  • Code that responds to the "incorrect username or password" error

So, are you testing that your database works? Or that your code that checks the validity works?

I would fake out the code that retrieves an existing account, and make it responds "here's the account data" in one unit test, and "there's no matching account" in another, to verify that your login code responds the right way, by either logging in the user, or responding with an error, and then assert against that.

Note that at some point you need to do an actual integration test as well, since you want to ensure that your code that queries Active Directory works properly, but you should test as much behavior as possible without involving Active Directory, it will make your tests more readable (everything is in one place), more maintainable (no need to log into Active Directory to produce new test data), and more trustworthy (no wondering when it fails if someone has messed up Active Directory, the network was flaky, user has been deleted, software upgraded so responds differently, etc.).

I've seen far too many "unit tests" fail due to external dependencies, and my advice is to try to minimize those as much as possible, ideally having none at all. For your unit tests that is.

Lasse V. Karlsen
There is no database for this particular method. This method gets invoked by a web form that takes a username and password. The method validates this against active directory by checking groups in AD and makes sure that the user is in a specific group, but not in other groups. I'm thinking that I need to create users on the fly, add them to the sequence of groups that should pass (and fail) and then run the tests.
Rob
As I said, you should not use your live Active Directory installation for this. Instead, fake out the data provider that tells you which groups people are in, and assert that your program behaves correctly. If you're talking to the Active Directory server, you're doing integration testing, not unit testing.
Lasse V. Karlsen
okay.. what would be the best way to fake out the data provider?
Rob
Create a new class, which implements the same interface as the one you're trying to fake out, or use an isolation framework (TypeMock, Moq, NMock, etc.) to produce it, and return known data from your methods there.
Lasse V. Karlsen
You should look at what isolation frameworks can give you, Roy Osherove from TypeMock has a lot of very good material on the net.
Lasse V. Karlsen