Use reflection. In my project, I write test for each domain object. Test checks if toString
method comes from Object
class or from my class. Code for that test
/**
* Passes if class has overridden toString method. Fails otherwise.
*/
public static void toStringTest(Object o) throws NoSuchMethodException {
Class<?> clazz = o.getClass().getMethod("toString").getDeclaringClass();
assertThat(clazz).isNotEqualTo(Object.class)
.withFailMessage("expecting method toString to be defined in actual class");
assertThat(o.toString()).isNotEmpty();
}
Then having class SomeClass
, In SomeClassTest
I invoke it as follows
public void shouldOverrideToString() throws NoSuchMethodException {
TestUtils.toStringTest(new SomeClassTest());
}
If you want to identify all classes that do not override toString, you may write tool that will scan classpath and invoke such test for every class (from your package). But this approach has limitations. Not all classes require toString. Service classes, REST controllers, etc do not need toString. So automation will give you a lot of false positives. You may scan only packages with model classes (if you keep model in separate package) or annotate model classes with custom annotation (and then scan only annotated classes) but I think such solutions are not worth the effort.
Finally, you may use https://projectlombok.org/ https://immutables.github.io/ or https://github.com/google/auto/tree/master/value
Those libraries use code generation/anotation processing to auto-generate equals/hashcode/toString. I use Immutables and it works very well. Even migration legacy data model to Immutables is straightforward.
In my project, I write such test for every domain object.