views:

99

answers:

4

I'm using NHibernate to persist this entity:

public class Store
{
    public int Id { get; protected set; }
    public int Name { get; set; }
}

Note how the Id property has a protected setter. This is to prevent users from changing the Id while still allowing NHibernate to assign it an Id when it saves it to the database.

In one of my unit tests, I'm using Moq with the following code to mock out my repository:

var mock = new Mock<IRepository>();
mock.Setup(x => x.GetById<Store>(It.IsAny<int>()))
    .Returns(new Store { Value = "Walmart" }); // can't set the ID here

var store = Repository.GetById<Store>(5);
Assert.That(store.Id == 5);

When I tell Moq to return a new Store instance, I can't assign the ID, and the unit test fails. How do I unit test this property? I don't want to change the access level of the property because I don't want users to change it manually, and yet that's exactly what I have to do here in order to test it.

+3  A: 

In the test project create a child class of Store that allows for customization of the protected properties.

class TestableStore : Store { 
  public int TestableId { 
    get { return Id; }
    set { Id = value; }
  }
}

Then setup your unit tests to use return this instance when you need to construct a Store object.

mock
  .Setup(x => x.GetById<Store>(It.IsAny<int>()))
  .Returns(new TestableStore { Value = "Walmart", TestableId=42 }); 
JaredPar
FYI, just need to add the Store class as the base class (I am not powerful enough to edit :()
aqwert
@aqwert doh! thanks, made the update
JaredPar
+2  A: 

If you're not actually testing the Store class, then mock it, and use the SetupGet method:

var mock = new Mock<IRepository>();
var mockStore = new Mock<Store>();
mock.Setup(x => x.GetById<Store>(It.IsAny<int>())).Returns(mockStore.Object);

mockStore.SetupGet(s => s.Id).Returns(5);
mockStore.SetupGet(s => s.Value).Returns("Walmart");

var store = Repository.GetById<Store>(5);
Assert.That(store.Id == 5);
arootbeer
Thanks, I never considered mocking out the store object itself!
Daniel T.
You're welcome. I normally use this with interfaces, but since you already have to have everything virtual for NHibernate anyway this is a great fit.
arootbeer
+2  A: 

Just to throw this out there as another approach, you could make the setter protected internal:

public class Store
{
    public int Id { get; protected internal set; }
    public int Name { get; set; }
}

and use the InternalsVisibleTo attribute:

[assembly: InternalsVisibleTo("StoreUnitTests")]
adrift
Hey that's pretty cool. Hadn't seen that before.
Kevin McKelvin
A: 

Certainly not the best approach, but you could also use reflection to set the property as is done in Sharp Architecture's tests.

DanP