Override configuration programmatically from unit tests
I used to think of a function as something which would convert some input value into some output value (potentially with some side-effects). And thus unit testing a function would involve passing particular inputs into the function and checking that the results were as expected (potentially setting up some database rows or something to test that the side-effects were executed properly).
But sometimes a function relies on a particular piece of global configuration. That's an input to the function too. For example the tax rate.
public int calculateVat(int cents) { double vat = config.getDouble("vatRate"); return (int) Math.round(cents * vat); }
Initially I would just test the function with the current settings of the config file.
// VAT is currently 20% in Austria assertEquals(20, obj.calculateVat(100));
However that's obviously not a great solution as that will break when the config file changes. And after all, configuration files are there to extract the things that likely will change from the otherwise often very long but hopefully reasonably static domain logic.
So the solution I use now is to extend such configuration accessing classes with methods such as "setValueForTesting". The "forTesting" part of the name indicates clearly its purpose is for test programs only.
config.setDoubleForTesting("vatRate", 0.2); assertEquals(20, obj.calculateVat(100));
That code feels much better. There are actually two advantages:
- Obviously the test code will not break if the config file changes.
- But also there is more locality. Everything you need to understand about that test is there in the test program's source file, in two easy-to-read lines.
But this approach feels somewhat unorthodox. How do other people do it?