This really depends. If the values your helpers operate on are primitives, then static methods are a good choice, as Péter pointed out.
If they are complex, then SOLID applies, more specifically the S, the I and the D.
Example:
class CookieJar {
function takeCookies(count:Int):Array<Cookie> { ... }
function countCookies():Int { ... }
function ressuplyCookies(cookies:Array<Cookie>
... // lot of stuff we don't care about now
}
class CookieFan {
function getHunger():Float;
function eatCookies(cookies:Array<Cookie>):Smile { ... }
}
class OurHouse {
var jake:CookieFan;
var jane:CookieFan;
var cookies:CookieJar;
function makeEveryBodyAsHappyAsPossible():Void {
//perform a lot of operations on jake, jane and the cookies
}
public function cookieTime():Void {
makeEveryBodyAsHappyAsPossible();
}
}
This would be about your problem. You can make makeEveryBodyAsHappyAsPossible
a static method, that will take in the necessary parameters. Another option is:
interface CookieDistributor {
function distributeCookies(to:Array<CookieFan>):Array<Smile>;
}
class HappynessMaximizingDistributor implements CookieDistributor {
var jar:CookieJar;
function distributeCookies(to:Array<CookieFan>):Array<Smile> {
//put the logic of makeEveryBodyAsHappyAsPossible here
}
}
//and make a change here
class OurHouse {
var jake:CookieFan;
var jane:CookieFan;
var cookies:CookieDistributor;
public function cookieTime():Void {
cookies.distributeCookies([jake, jane]);
}
}
Now OurHouse
need not know about the intricacies of cookie distribution rules. It must only now an object, which implements a rule. The implementation is abstracted away into an object, who's sole responsibility is to apply the rule. This object can be tested in isolation. OurHouse
can be tested with using a mere mock of the CookieDistributor
. And you can easily decide to change cookie distribution rules.
However, take care that you don't overdo it. For example having a complex system of 30 classes act as the implementation of CookieDistributor
, where each class merely fulfills a tiny task, doesn't really make sense. My interpretation of the SRP is that it doesn't only dictate that each class may only have one responsibility, but also that a single responsibility should be carried out by a single class.
In the case of primitives or objects you use like primitives (for example objects representing points in space, matrices or something), static helper classes make a lot of sense. If you have the choice, and it really makes sense, then you might actually consider adding a method to the class representing the data, e.g. it's sensible for a Point
to have an add
method. Again, don't overdo it.
So depending on your problem, there are different ways to go about it.
Don't do any processing in the fromStream()
method, just call another method - something like procesStreamResult()
that get called whenever something comes in from the stream. This way, you can test procesStreamResult()
by calling it with mock objects as arguments and also implement proper error handling and unit testing.
What I'm basically trying to say is: decouple the actual outside dependency (the stream, in your case) from the internal workings of your own code and only test the code you need to test.
Best Answer
Not with all helper methods, but with helper methods that are used in more than one test class.
Design your tests the same way as you implement business classes!
Refactor code duplicates within a class into a local method. If the method is used in different test classes move it into a different test helper class that is used by different tests.
So my
OrderTests
class has a local methodassertEqual(String message, IOrder expected, IOrder actual)
and my helperTestDataFactory
has a static methodcreateTestOrder()
that is used inOrderTests
,PriceCalculationTests
,PaymentTests
,DeliveryTests
.A test may use one or more of the standard factory methods and modifies it as needed. Example: