tags:

views:

88

answers:

2

I've been told not to use implementation details. A dependency seems like an implementation detail. However I could phrase it also as a behavior.

Example: A LinkList depends on a storage engine to store its links (eg LinkStorageInterface). The constructor needs to be passed an instance of an implemented LinkStorageInterface to do its job. I can't say 'shouldUseLinkStorage'. But maybe I can say 'shouldStoreLinksInStorage'.

What is correct to 'test' in this case? Should I test that it stores links in a store (behavior) or don't test this at all?

+1  A: 

LinkStorageInterface is not an implementation detail - its name suggests an interface to to an engine. In which case the name shouldUseLinkStorage has more value than shouldStoreLinksInStorage.

That's my 2 pennies worth!

Preet Sangha
+3  A: 

The dependency itself is not an expected behavior, but the actions called on the dependency most certainly are. You should test the stuff you (the caller) know about, and avoid testing the stuff that requires you to have intimate knowledge of the inner workings of the SUT.

Expanding your example a little, lets imagine that our LinkStorageInterface has the following definition (Pseudo-Code):

Interface LinkStorageInterface

  void WriteListToPersistentMedium(LinkList list)

End Interface

Now, since you (the caller) are providing the concrete implementation for that interface it is perfectly reasonable for you to test that WriteListToPersistentMedium() gets called when you invoke the Save() method on your LinkList.

A test might look like this, again using pseudo-code:

void ShouldSaveLinkListToPersistentMedium()

  define da = new MockLinkListStorage()  
  define list = new LinkList(da)

  list.Save()

  Assert.Method(da.WriteListToPersistentMedium).WasCalledWith(list)

end method

You have tested expected behavior without testing implementation specific details of either your SUT, or your mock. What you want to avoid testing (mostly) are things like:

  1. Order in which methods were called
  2. Making a method, or property public just so you can check it
  3. Anything that does not directly involve the expected behavior you are testing

Again, a dependency is something that you as the consumer of the class are providing, so you expect it to be used. Otherwise there is no point in having that dependency in the first place.

Josh
+1: Don't test the implementation. Test the observable API.
S.Lott