views:

110

answers:

3

I am working on writing unit tests properly, and I wonder is it bad technique to test the result of a method under test by calling another method to verify the result?

ie. in the below example I can only check that an StoreObject method call was successful(ie. a object being stored in the cache) by calling either FetchObject or the HasCachedObjects property, both of which contain logic that should be tested separately. What would you do in this case where the result is hidden from the public API?

I have a Cache class:

public class Cache {

  private Dictionary<string, object> _Cache = null;

  public bool HasCachedObjects {
    get {
      if (_Cache.Count > 0) {
        return true;
      } else {
        return false;
      }
    }
  }

  public Cache() {
    _Cache = new Dictionary<string,object>();
  }

  public void StoreObject(string key, object obj) {
    _Cache[key] = obj;
  }

  public object FetchObject(string key) {
    if (_Cache.ContainsKey(key)) {
      return _Cache[key];
    }

    return null;
  }
}
+2  A: 

Not at all. In fact, those are probably two different tests - one to verify that HasCachedObjects is true after caching an object, and one to verify that you can retrieve an object after storing it.

(I'm not really sure what this class does except wrap a Dictionary in a slightly different API, but that's another topic...)

kyoryu
Tis a very simplified example class for the question... and how is that a 'topic'?
theringostarrs
Because the class doesn't seem to have much value, so it's hard to really figure out how to test it. In general, I avoid state-based testing, but it's really the only thing you can do with the design presented. I usually use TDD and unit testing to specify the requirements of the class' behavior, and then write the code to match that... in this case, it's not clear what the class is actually doing, or is supposed to do, so how to test it is equally unclear.
kyoryu
But to add to what TrueWill says, I agree - don't think of a test as testing a specific method, think of it as testing a particular behavior of a class. A method may be invoked by more than one test, and a test may invoke more than one method...
kyoryu
I think its pretty obvious, store or fetch an object. Think about it this way...How would you test a Dictionary? WHy do you avoid state based testing?
theringostarrs
For value objects and containers, state-based testing is clearly the thing to do, but for things that fall more under 'object' than 'value', interaction testing is often superior. What you don't want to do is testing by side effect, as that's often not really unit testing, and is testing an entire chain of objects.
kyoryu
+2  A: 

Don't think of a test case as testing a method; think of it as testing a unit of functionality (or perhaps a use case).

So your test might be StoreObject_WhenSuccessful_AddsToCache or some such.

And yes, I'd confirm the test via the public API.

TrueWill
A: 

Instead of testing individual methods you can test different use-cases / scenarios, for example: add to cache - check the object is there, etc...

Alexander Kojevnikov