Search code examples
tddrhino-mockss#arp-architecturesharp-architecture

Testing state in S#arp Architecture - Best practice


How do I test for state in a S#arp Architecture project?

For example, I have a custom RoleProvider. I want to test the method provider.AddUsersToRoles(string[], string[]).

So I start with:

// Arrange
const string ficticiousRole = "Management";
var userToExpect = UserInstanceFactory.CreateValidTransientUser();
var roleToExpect = RoleInstanceFactory.CreateValidTransientRole();

userRepository.Expect(r => r.GetByUsername(userToExpect.Username))
              .Return(userToExpect);
roleRepository.Expect(r => r.GetByName(ficticiousRole))
              .Return(roleToExpect);

var userNames = new List<string>();
var roleNames = new List<string>();
userNames.Add(userToExpect.Username);
roleNames.Add(ficticiousRole);

Then I add the user to a role. Then I check if the user is in this role.

// Act
roleProvider.AddUsersToRoles(userNames.ToArray(), roleNames.ToArray());
var isNewUserInRole = roleProvider.IsUserInRole(userToExpect.Username, ficticiousRole);

// Assert
Assert.IsTrue(isNewUserInRole);

The problem is that I'm using Rhino Mocks. I have limited knowledge of Rhino Mocks, but from what I understand (according to Ayende Rahien) you use Rhino Mocks to test for operations, not state.

So I guess an in-memory SqlLite db would be more suitable? What's the best way to do this in S#arp Arch?


Solution

  • You can't do that with Rhino Mocks since that is simply a mocking framework that fakes things like database calls, etc. It sounds like you actually want to test persistence to the database which is basically database integration testing. In that case, you would most definitely want to use an in-memory database such as SqlLite (if possible!) as opposed to hitting a SQL Server instance.

    What you want to do is at the beginning of each test or test class is tear down the database if it exists already, rebuild the database, populate the database with some seed data and then test your database interaction. This way, you can ensure you have a known database state before each test is run.

    One thing I did on a project was grouped all of my read-only tests into one test class so that I only had to do the database rebuild step once for the class and moved all my delete, update and insert tests into other test classes that rebuilt the database before each and every test. Given enough tests, this can be quite time consuming and may want to be relegated to CI server.