views:

46

answers:

1

The following is a simple test of a repository against FluentNHibernate-1.1.0.685 (NHibernate-2.1.2.4000). The Session and NH config are provided by the test fixture.

[Test] public void ShouldEdit() {
    var employee = CreateEmployee();
    session.Clear();

    var changedEmployee = _testRepository(employee.id);
    changedEmployee.FirstName = "Ringo";
    _testRepository.SaveOrUpdate(changedEmployee);

    session.Flush();
    session.Clear(); // Pulling this call will allow the test to pass.

    var employees = (IList)_testRepository.GetAll();
    Assert.Contains(changedEmployee, employees);
    Assert.IsFalse(employees.Contains(employee));
}

Employee CreateEmployee() {
    var e = {Id = 1, FirstName = "George", LastName = "Washington" };
    _testRepository.SaveOrUpdate(e);
    session.Flush();
    return e;
}

This test will pass if I get rid of the second call to Clear(). If I leave the call in however then the test will fail with the following:

Failed:
Expected: Collection containing <Employee>
But was: < <Employee> >

Not very helpful. Leaving that aside, why do I need to remove the second call to Clear()?

Flush() will sync with the db and, if I understand the documentation correctly, Clear() will evict the session cache. This seems to be exactly the behavior I want so that I can be sure I'm not testing against stale data. In fact I would expect the test to fail without the call to Clear() and yet this isn't the case. Can someone shed some light on this behavior?

(Note: This is a variation on a repository test found in Chapter 10 of the PragProg book "Test Drive ASP.Net MVC". Good book btw.)

+6  A: 

Because your Contains method is checking for reference equality, whereas you probably want to check for equality using the Id or employee's name.

Calling Clear() will remove the reference to changedEmployee from NHibernate's Session (NHibernate won't use this reference any more). This means when you reload the employees, a new instance of the changed employee is created. This reference won't pass a reference equality check with the original changedEmployee object (although all its properties should be the same).

Without the Clear(), NHibernate maintains a reference to the changedEmployee object and this same reference is returned by the GetAll method.

cbp
Thank you. That makes perfect sense.
RG