Twitter LinkedIn Github

JetBrains

In a follow-up to my previous post on mocking, here is the same code re-factored so that it does not depend on the internal behavior of GetAllEmployeesByCompanyId

 

   1: [TestMethod]
   2: public void GetAllEmployeesByCompanyId_When_Employees_Are_Marked_Returns_Non_Marked_Employees()
   3: {
   4:     IEmployeeRepository employeeRepository = MockRepository.GenerateMock<IEmployeeRepository>();
   5:  
   6:     User user = new User { Id = Guid.NewGuid()};
   7:  
   8:     Employee employee = new Employee {Id = Guid.NewGuid()};
   9:  
  10:     Employee deletedEmployee = new Employee { Id = Guid.NewGuid(), DeletedBy = user};
  11:  
  12:     employeeRepository.Stub(x => x.GetEmployeesByCompanyId<Employee>(Guid.Empty)).Return(new List<Employee>
  13:                                                                                              {
  14:                                                                                                  employee,
  15:                                                                                                  deletedEmployee
  16:                                                                                              });
  17:  
  18:     var EmployeeServices = new EmployeeServices(employeeRepository);
  19:  
  20:     var employees = EmployeeServices.GetAllEmployeesBy
CompanyId(Guid.Empty);
  21:  
  22:     Assert.AreEqual(1, employees.Count);
  23: }

I've done quite a bit of re-factoring, taking advantage of some of the C# 3.0 language features. I'm also using RhinoMocks 3.5 which also makes use of extension methods. In general the test is much cleaner, less noise. In fact, apart from two "strange" calls (lines 4 and 12), you wouldn't even notice it's using mocks.

The important change is that its no longer brittle. If you recall correctly, from my previous post, the purpose of the test was to validate that when GetAllEmployeesByCompanyId, only records not marked for deletion were returned. It was not about interaction or the internal behavior of the call. As such, we've removed this tight coupling to the actual implementation by

a) Replacing the strict mock with a dynamic mock [Line 4].
In version 3.5 of RhinoMocks, you no longer need to create a mock repository if you don't want to. As such, you have static methods on the MockRepository class that generate mocks for you. By default, the mock generated is Dynamic. Therefore, the call MockRepository.GenerateMock is a dynamic mock.

b) Removing the call to VerifyAll.
Since we do not set any expectations, we do not really need or want to verify that any specific calls were made. Again, that's not the purpose of this particular test.

In line 12, we've stubbed the call to GetEmployeesByCompanyId of EmployeeRepository so that it returns a list with two employees. If the repository call were to not return a value, we wouldn't even need to explicitly stub it.

As you can see, we are still using mocks, yet we are not making our test volatile to change. We are using mocks to mock out non existent functionality. This doesn't mean to say that we shouldn't use mocks for verifying behavior. But we should only do that if the purpose of the test is that. In this case it isn't.

RhinoMocks 3.5 is pretty cool. It allows a lot of the noise surrounding mocking to be eliminated in tests. Hopefully I'll blog more about it as I use this version more, but be sure to check it out (Don't be lazy...Just Google it!)