I am a .Net developer coding in C#, and I have been assigned to a project that its manager wants it to be thoroughly unit tested, mostly emphasising isolation so that one logical bug ideally fails one test, and there are no dependencies between tests.
Today we are discussing testing patterns, and the following question has arised:
Lets say we have an object named MyHashTable
, that implements:
void Add(string key, string value);
string GetValue(string key);
We want to test each of those methods independently. The main problem of course, logically we can't get what we never added, and we can't verify something was added without getting it. We have heard and read about stubbing/mocking and other techniques that might help overcome this issues, but can't decide which solution would be most readable and maintanable.
Therefore I ask for advices/ideas how to test those methods in isolation, and if you may, include pros and cons for your suggestion. Thank you!
If you want to achieve full independence and isolation, then you'll most likely have to expose some internals of MyHashTable
. For example, underlying collection that Add
adds elements to:
public class MyHashTable<TKey, TValue>
{
internal Dictionary<TKey, TValue> Storage { get; set; }
// ...
}
This isn't very pretty as you can see, but like I said, it's not possible to test those two methods in full isolation without exposing something (like you noticed, it's a method pair). You can naturally provide other ways to initialize your class, eg. with constructor taking collection, but it only delegates problem one step further - you'll need to verify that constructor worked as well, and you'll probably need Get
method for that... which brings you back to original problem.
Edit:
Note that I'm not suggesting revealing internals/implementation details as the only path to follow. You can simply test those methods together (not as in single test, but one utilizing other), which might prove to be better solution. Sure - if your Add
at some point fails, Get
tests will fail too. But then again, you want to fix broken Add
- once that's done everything is back to normal. Problem naturally lies in how do you distinguish whether it was Add
or Get
that got broken - but that's where proper assertion failure messages or guard assertions concept I linked in comment come in handy.
Truth is, sometimes full separation and isolation is way too difficult to achieve or simply would need you to introduce poor design. That's one of the reasons they should never be final goal.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With