CITCON Paris 2009: Mock objects
Interfaces
During the session on mock objects there was a digression about interfaces. I have seen too often interfaces in a way that I don't like. I will use the same example as Eric:
Let's say that you have a FileManager
, providing some services to manage files I suppose 😉, you may have an interface called IFileManager
. And usually there is only one implementation of IFileManager
which is FileManager
.
I think this is wrong for at least two reasons:
- Usefulness. If there is only one implementation, why do you need an interface?
- Naming. The interface name should represent the "role", so
FileManager
is suitable for the interface name,IFileManager
has no meaning. Then the implementation should reflect what kind of implementation you have, likeLocalFileManager
,DistributedFileManager
or aDummyFileManager
for your tests (but not an uglyFileManagerImpl
).
So usually, when I see a software with that kind of 1 to 1 relationship between interface and implementation and using bad names, it raises a warning light in my head, telling me that the person who wrote that code did not really know what he was doing (only applying some old and bad coding rules without trying to understand why it was useful for). As Antonio says, prefix "I" for interface and suffix "Impl" for implementations are signs of code smell.
I even have seen some interfaces with only one or two methods, the implementation had a lot more methods… and the concrete class was directly used in other classes… so yes, very useful interface 😕.
Sometimes, when writing tests, I need to mock some classes that I haven't defined any interface for… and since several mock libraries are able to mock concrete classes I still not extract any interface.
I like simple classes, with simple roles, so mostly all public methods (except constructor and setters) are the "implied" interface.
So my point on interfaces is "use an interface only when you really need it" (that reminds me YAGNI):
- when you need several implementations of a given "role",
- when defining some "ability" (sorry I didn't find the right term) like
Clonable
,Closable
,Comparable
,Serializable
,Anything-able
(if you can add "able" at the end, it's a good sign that you might be able to extract an interface for that 😉).
Mock objects
So yes, we also spoke about mock objects. Steve Freeman was trying to explain us some stuff, I have the feeling that there was something in his speech that was enlightening but I didn't really get it (that's why it's only a feeling for the moment).
What I remember is that, when writing tests:
- mock the collaborating classes that change the outside world,
- use stubs, dummy implementations, etc. otherwise.
I don't fully understand the reason yet. But something I learn recently and that was says during the session: mock only the code you own, don't mock external resources.
So for instance, if you have a Customer
object, a table full of customers in your database, don't try to mock JDBC classes like Connection
, ResultSet
and so on. Create a class accessing the data, let say CustomerDAO
(I don't like the name, but hey, it's only an example), and then you can mock your CustomerDAO
in your software.
I imagine that CustomerDAO
will then be tested in integration tests (it's a class using external software/server/stuff right? Can't really unit test it (except maybe some data storage specific logic I may have to write in it)).
Anyway, it was an interesting session.
Misc
Books recommended during the session:
- Growing object-oriented software guided by tests by Steve Freeman and Nat Pryce.
- Object design by Rebecca Wirfs-Brock and Alan McKean.
- xUnit test patterns by Gerard Meszaros.
Frameworks:
Comments Add one by sending me an email.