I'm trying to wrap my head around implementing MVC with as much useful abstraction as I can for purposes of automated unit testing. In the process, I came up against an interesting conundrum: How and where do I declare the mock object for my database?
Here's what I have.
- ContactView is a form that implements IContactView. It has knowledge of IContactModel so that it can update itself in response to event notifications from the model object.
- Contact is a class that implments IContactModel. It encapsulates the business rules for manipulating the object, as well as the code for fetching from/updating data in the data access layer.
- ContactController is a class that implements IContactController and has knowledge of both IContactModel and IContactView.
- Database is a class that implements IDatabase and contains methods for selecting, inserting, updating, and deleting data in the database.
This, to me, is the tricky part. The model object needs to know how to interact with the IDatabase so that it can operate on either a real database or a mock object. The problem I am faced with is how to provide a reference to the database without violating Separation of Concerns.
I'd rather that the views and controllers had no knowledge of how the data was stored. That way, if I chose to do so later, I could swap out IDatabase for something like IJsonStore or IXmlStore and only have to touch the model classes. I don't want my views & controllers making any assumptions about where and how the data is stored.
I see a couple of probable solutions, but I am not certain what the best one is.
- I can declare a singleton that exposes a public property, Database (of type IDatabase). This way, the unit tests could set the database to a mock object, and production code would set it to a production database. But that means that production code, at some point, would have to know about IDatabase. I suppose that's unavoidable; but I am hoping there's some other solution that's preferable.
- I can modify the model classes to maintain a reference to the database, taking it in the constructor. This seems undesirable simply because it results in a lot of additional code. And, I'm brought right back to square one: Whomever declares the model instance has to know which IDatabase object I want to use.
I'm sure there are alternatives out there, and that I'm just unaware of them. So I'm throwing this out there: How would you guys do this, and what have you seen that worked well?
Thanks in advance.