I was asked this question on StackOverflow. Here's what I had to say:
Is DevForce testable? Here are the beginnings of a proper answer.
It's a potentially contentious question. People have strong feelings about what makes something testable. Let me confine myself to specific testing scenarios .. and then you judge the degree to which we meet your testing requirements.
1) DevForce supports pure POCO entities if that's your preference. Most people will prefer to use the entities that derive from our base Entity class so I will confine my subsequent remarks entirely to such entities.
2) You can new-up such an entity using any ctor you please and get and set its (non-navigation) properties with no other setup.
var cust = new Customer {ID=..., Name =...}; // have fun
Assembly references are required of course.
3) To test its navigation properties (properties that return other entities), you first new an EntityManager (our Unit-of-Work, context-like container), add or attach the entities to the EM, and off you go. Navigation properties of the Entities inheriting from our base class expect to find related entities through that container.
4) In most automated tests, the EntityManager will be created in a disconnected state so that it never attempts to reach a server or database.
You might add to it an Order, a Customer, some OrderDetails; note that all of them are constructed within the context of your tests ... not retrieved from anywhere.
Now order.Customer returns the test Customer; order.OrderDetails returns your test details. Your preparation consists of creating the EM, the test entities, ensuring that these entities have unique IDs and are associated.
Here's an example sequence:
var mgr = new EntityManager(false); // create disconnected
var order = new Order {ID = ..., Quantity = 1, ...};
var customer = new Customer {ID = 42, Name = "ABC", };
mgr.AttachEntity(order);
mgr.AttachEntity(customer);
order.Customer = customer; // associate them
The EM is acting as an in-memory database.
5) You can use LINQ now
var custs = mgr.Customers.Where(c => c.Name.StartsWith("A").ToList();
var orders = mgr.Orders.Where(o => o.Customer.Name.StartsWith("A")).ToList();
6) Of course I always create a new EntityManager before each test to eliminate cross-test pollution.
7) I often write a so-called "Data Mother" test helper class to populate an EM with a standard collection of test data, including deviant cases.
8) I can export an EntityManager's cache of test entities to file or a test project resource. When tests run, a DataMother can retrieve and restore these test entities.
Observe that I am moving progressively away from unit testing and toward integration testing. But (so far) my tests do not require access to a server, or Entity Framework, or the database. They run fast and they are less vulnerable to distracting setup failures.
Of course you can get to the server in deep integration tests and you can easily switch servers and databases dynamically for local, LAN, and web scenarios.
9) You can intercept query, save, change, add, remove, and other events for interaction testing.
10) Everything I've described works in both regular .NET and Silverlight and with every test framework I've encountered.
On the downside, I wouldn't describe our product as mock-friendly.
I readily concede that we are not Persistence Ignorant (PI). If you're a PI fanatic, we're the wrong choice for you.
We try to appreciate the important benefits of PI and do our best to realize them in our product. We do what we can to shunt framework concerns out of view. Still, as you see, our abstraction leaks in a few places. For example, we add these members to the public API of your entities:
- EntityAspect (the gateway to persistence awareness)
- ErrorsChanged
- PendingEntityResolved
- PropertyChanged
- ToQuery<>
Personally, I would have cut this to two (EntityAspect, PropertyChanged); the others snuck by me. For what it's worth, inheriting from Object (as you must) contributes another extraneous five.
We feel that we've made good trade-offs between pure P.I. and ease-of-development.
My question is "does it give you what you need to validate expectations without a lot of friction ... along the entire spectrum from unit to deep integration testing?"
I'm eager to take suggestions on how we can improve our support for application testing.
Feel free to follow-up with questions about other testing scenarios that I may have overlooked.
Hope this helps
Ward