0

So when building my domain model i am trying to be pragmatic about exposing only whats necessary for driving the behavior but my unit tests are requiring me to expose public getters that are only really needed from within the class. how is everyone handling this? my domain layer is only being accessed through my application services layer, so is it really that big of a deal? should i make them internal and give the test project access?

any help would be great!

Marco
  • 2,453
  • 3
  • 25
  • 35

4 Answers4

2

I think it is always a bad idea to change the public interface of a class to accommodate a unit test. That is the "tail wagging the dog".

If you must access internal state of an object to test it, I would create some extension methods in my testing namespace that allow easy access to an object's private properties (e.g., T GetPropertyValueByName(this string propertyName).

Eric Farr
  • 2,683
  • 21
  • 30
  • Visual Studio can generate wrappers that allow access to internal details http://msdn.microsoft.com/en-us/library/bb385974.aspx – Todd Smith Jul 18 '11 at 18:47
1

Without seeing your code it seems that your design might need to be changed to make it more testable. Think about extracting an interface and implimenting dependancy injection to your class so you can set internal state if you need to. Using this method, you can set private members during construction. Also try using a mocking library. Moq is my favorite.

Ryan Bennett
  • 3,404
  • 19
  • 32
0

You can make the unit test library a friend of the domain library and change the private members of your domain classes to internal.

scottm
  • 27,829
  • 22
  • 107
  • 159
0

I agree with Eric's statement that unit tests should not affect class APIs.

In your situation, it sounds like your design may not be quite correct. You're talking about unit tests that need to check private variables - but a unit test should be fully defined using public APIs.

Either split up your objects so that the private fields are exposed at some layer (making the objects more fine-grained), or change your tests to not need access to those private fields (making your unit tests more coarse-grained).

One useful tool is Code Contracts. You can define very fine-grained tests (post-conditions and object invariants, defined in terms of private fields) using Code Contracts, and make your unit testing a little more coarse-grained. Some of my unit tests do nothing more than invoke a method and ensure the Code Contracts don't fire.

Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810
  • I have a Story class with a method call Submit. Within that method, i set a submitted on date property. Now, that property value is not used anywhere in my domain layer. BUT the read layer uses it for display purposes. Does that help? Making it public for the sole reason of the UI smells. My tests assert against it to make sure it is properly set. – Marco Jul 18 '11 at 18:06
  • @Marco if the property SubmittedOnDate is a property of a story, what's wrong with making it public? – scottm Jul 18 '11 at 18:09
  • I don't think that would smell. I'm a proponent of each layer being independent, with its own public API (no internals unless absolutely necessary). So either the `Story` class has a `SubmittedDate` property or it does not; if it does not, then the UI layer can't use it; if it does, then the unit test can use it too. To me, having an internal `SubmittedDate` only read by the UI layer is a code smell - it's a hidden API hacked onto the `Story` class which only exists because of your specific UI layer. The design dependency there is going the wrong way. – Stephen Cleary Jul 18 '11 at 18:12
  • I've just been some articles on DDD and they seem to talk about the evil in exposing public setters and getters, that's all. – Marco Jul 18 '11 at 18:13
  • I've read a few pieces against public getters/setters, too; but I end up saying meh to them. I just can't see where removing properties makes a significant improvement in the design. – Stephen Cleary Jul 18 '11 at 18:15
  • @Stephen I see what you are saying. The only thing different as that i am using a seperate model (Linq 2 SQL) for my UI layer, so that property is public within that model. – Marco Jul 18 '11 at 18:17
  • @Marco, hiding a public setter is different than hiding both the getter and setter. You can make the property getter public and the setter private and that should solve your problem. The Submit() method can still change the date and you can still see it. – scottm Jul 18 '11 at 18:19
  • @Marco: Heh, DDD proponents would sure have something to say about using LINQ2SQL directly from your view! :) At this point, I'm not sure how LINQ2SQL would work in conjunction with your domain layer. It sounds like your view is *bypassing* your domain layer to talk directly to the database, which is generally frowned upon (if you want real layers, that is). – Stephen Cleary Jul 18 '11 at 18:21
  • @Scottm that is actually how i got it implemented now, i was just concerned i was approaching this the wrong way. – Marco Jul 18 '11 at 18:22
  • @Stephen I am using a flavor or CQRS without the event sourcing. the one benefit i've seen thus far is that our existing db is very deep with relationships and so my domain model does not need all the crazy associations to show some random item way deep down. so i've been utilizing database views to hide this form the UI layer and querying against them from my controllers. – Marco Jul 18 '11 at 18:25