Consider auto-generating assertThat and subject factory for custom subjects
See original GitHub issueCurrently a minimal Truth Subject requires four operations: a constructor, an assertion method, and two static methods for accessing the subject: assertThat and a subject factory (see extension page).
Would it be possible to auto-generate these methods and, possibly, accumulate all custom assertThat overloads in a single place, to cut down the number or operations the developer has to add to a custom subject, and encourage creating custom Subjects even if a single assertion method is needed?
For instance,
@AutoSubject(factoryName = "employees")
public final class EmployeeSubject extends Subject {
private final Employee actual;
// The constructor needs to be public if the class with `assertThat`
// might be outside of its package
public EmployeeSubject(FailureMetadata failureMetadata, @NullableDecl Employee subject) {
super(failureMetadata, subject);
this.actual = subject;
}
// User-defined test assertion SPI below this point
public void hasName(String name) {
check("name()").that(actual.name()).isEqualTo(name);
}
}
Will generate these two methods:
// User-defined entry point
public static EmployeeSubject assertThat(@NullableDecl Employee employee) {
return assertAbout(EMPLOYEE_SUBJECT_FACTORY).that(employee);
}
// Static method for getting the subject factory (for use with assertAbout())
public static Subject.Factory<EmployeeSubject, Employee> employees() {
return EMPLOYEE_SUBJECT_FACTORY;
}
// Boiler-plate Subject.Factory for EmployeeSubject
private static final Subject.Factory<EmployeeSubject, Employee> EMPLOYEE_SUBJECT_FACTORY =
EmployeeSubject::new;
As a new user of Truth, I can’t say if such implementations are common enough so that it makes sense to generate them. There are also other considerations:
- Visibility — if there are subjects for package-private types in several packages, the Truth won’t be able to produce a single file with all assertions. What shall it produce in this case — a file per subject, or per package?
- Discoverability — if Truth produces a single file with all assertions (which might not always work ^), it is trivial to import it knowing its name. But if it generates multiple files, it might be more difficult for the end-user to discover them.
#251, which suggested generating the factory, is likely related.
Issue Analytics
- State:
- Created 4 years ago
- Reactions:1
- Comments:7 (1 by maintainers)

Top Related StackOverflow Question
Thanks. This is something that we’ve given a little thought to in the past. I’ll try to summarize here.
The boilerplate is definitely unfortunate. While you can cut the 2 methods down to this…
…so that there’s no need for
EMPLOYEE_SUBJECT_FACTORY, that’s still a bunch of boilerplate (on top of the constructor and field, plus the actual assertion methods, as you note above).On top of that, there’s the possibility that we could generate the assertion methods themselves in straightforward cases (like the
namecase above).For those reasons, I do think we will look into this eventually.
I say only “eventually,” though, for a few reasons:
A little more on annotation processors that generate public API, cribbed from some internal documentation on the topic:
assertThatoremployeesdefined in the source.assertThat, and a code generator might do a better job of filling in a little boilerplate doc than a human would.)As per the PR, this is now available here: https://github.com/astubbs/truth-generator as a pre-release SNAPSHOT that can be installed locally. Will work on getting it into repo1 soon.