Rhino.Mocks and Read Only Property Injection

I came across an interesting issue tonight exploring the use of Rhino.Mocks in unit tests. I have a class UserRepository that implements my current understanding of the Repository Pattern. My repository uses the interface IDataProvider to persist my User entity. The concrete class UserDataProvider wraps NHibernate.

My goal was to write unit tests that cover the methods of UserRepository. I used Rhino.Mocks to mock away UserDataProvider to prevent actually needing a database.

Things were going fine:

public void SaveTest(){
    MockRepository mock = new MockRepository();

    IDataProvider dataProvider =
          (IDataProvider) mock.CreateMock<IDataProvider>();
    UserRepository target = new UserRepository(dataProvider);
    User u = new User();

    Expect.Call(dataProvider.Save(u)).Return(1);
    Expect.Call(dataProvider.GetById(1)).Return(u);

    mock.ReplayAll();
    User x = target.Save(u);
    mock.VerifyAll();

    Assert.AreEqual(x, u);
}
public void GetListTest(){
    MockRepository mock = new MockRepository();
    IDataProvider dataProvider =
         (IDataProvider)mock.CreateMock<IDataProvider>();
    UserRepository target = new UserRepository(dataProvider);

    Expect.Call(dataProvider.GetList()).Return(
        new List<object> { new User(), new User()});

    mock.ReplayAll();
    IList<User> users = target.GetList();
    mock.VerifyAll();
    Assert.AreEqual(2, users.Count);
}

Then I hit a snag. My User entity has a property Id that is read only. The users Id comes form the database and should not be able to be modified. So my next test has a bit of a problem and fails to compile.

public void GetByIdTest() {
    MockRepository mock = new MockRepository();

    IDataProvider dataProvider = (IDataProvider)mock.CreateMock<IDataProvider>();
    UserRepository target = new UserRepository(dataProvider);

    //TODO: Interesting Problem here. My actual dataProvider uses NHib
    //and would be able to meet this expectation. But my mock
    //cannot set the read only id property so this test will not
    //even compile.
    Expect.Call(dataProvider.GetById(1)).Return(new User() { Id = 1 });

    mock.ReplayAll();
    User u = target.GetById(1);
    mock.VerifyAll();

    Assert.AreEqual(1, u.Id);
}

NHibernate has no problem injecting the value when I fetch the object from it, but my simple little expectation above chokes on it. I am not sure how to get around this one with out violating the intent of the test. I'll have to dig into the Rhino.Mocks documentation and see what tools it offers to get around this situation.

So far Rhino.Mocks is a great time saver. If I actually had to generate a fake for IDataProvider it would take quite a bit of time. I'll have to work it into my regular work life and see how it fairs there.

I'll update this post when I find a resolution to the issue at hand.

Follow me on Mastodon!