Fluent assertion framework for Java that provides clear, readable test assertions and informative failure messages
—
Specialized utilities for testing assertion failures, soft assertions with batched failure reporting, and integration with testing frameworks.
JUnit TestRule that collects multiple assertion failures and reports them together at the end of the test.
/**
* Creates a new Expect instance for collecting assertion failures.
* @return a new Expect instance
*/
public static Expect create();
/**
* JUnit TestRule that can be used with @Rule annotation for automatic failure collection.
*/
public class Expect implements TestRule {
/**
* Creates an assertion about the given subject but collects failures instead of throwing immediately.
* @param actual the value under test
* @return Subject for making assertions
*/
public <T> Subject that(T actual);
/**
* Adds a custom failure message prefix for subsequent assertions.
* @param message the message to prepend to failure messages
* @return this Expect instance for chaining
*/
public Expect withMessage(String message);
/**
* Adds a formatted custom failure message prefix for subsequent assertions.
* @param format format string using lenient formatting
* @param args arguments for the format string
* @return this Expect instance for chaining
*/
public Expect withMessage(String format, Object... args);
/**
* Creates assertions using custom Subject factories.
* @param factory the Subject factory
* @return SimpleSubjectBuilder for custom assertions
*/
public <S extends Subject, A> SimpleSubjectBuilder<S, A> about(Subject.Factory<S, A> factory);
}Basic Usage Examples:
import static com.google.common.truth.Expect.create;
public class ExpectExampleTest {
@Rule
public final Expect expect = create();
@Test
public void testMultipleAssertions() {
User user = new User("Alice", 25, "alice@example.com");
// All assertions are collected - test continues even if some fail
expect.that(user.getName()).isEqualTo("Alice");
expect.that(user.getAge()).isGreaterThan(18);
expect.that(user.getEmail()).contains("@");
expect.that(user.isActive()).isTrue();
// If any assertions failed, they are all reported at the end
}
@Test
public void testWithCustomMessages() {
List<String> items = Arrays.asList("apple", "banana");
expect.withMessage("List should not be empty")
.that(items).isNotEmpty();
expect.withMessage("List should contain fruit")
.that(items).contains("apple");
expect.withMessage("List should have correct size")
.that(items).hasSize(2);
}
}Complex testing scenarios using Expect for comprehensive validation.
// Testing complex object validation
@Test
public void testComplexObjectValidation() {
Order order = createTestOrder();
// Customer validation
expect.withMessage("Customer validation")
.that(order.getCustomer()).isNotNull();
expect.that(order.getCustomer().getName()).isNotEmpty();
expect.that(order.getCustomer().getEmail()).matches(".*@.*\\..*");
// Order details validation
expect.withMessage("Order details validation")
.that(order.getItems()).isNotEmpty();
expect.that(order.getItems()).hasSize(3);
expect.that(order.getTotalAmount()).isGreaterThan(BigDecimal.ZERO);
// Order status validation
expect.withMessage("Order status validation")
.that(order.getStatus()).isEqualTo(OrderStatus.PENDING);
expect.that(order.getOrderDate()).isAtMost(Instant.now());
}
// Testing collection contents with multiple criteria
@Test
public void testCollectionValidation() {
List<Product> products = productService.getAllProducts();
// Collection-level assertions
expect.that(products).isNotEmpty();
expect.that(products).hasSize(expectedProductCount);
// Individual product validation
for (int i = 0; i < products.size(); i++) {
Product product = products.get(i);
expect.withMessage("Product %d validation", i)
.that(product.getId()).isNotNull();
expect.that(product.getName()).isNotEmpty();
expect.that(product.getPrice()).isGreaterThan(BigDecimal.ZERO);
expect.that(product.getCategory()).isNotNull();
}
}
// Testing API response validation
@Test
public void testApiResponseValidation() {
ApiResponse response = apiClient.getUserProfile(userId);
// Response structure validation
expect.that(response).isNotNull();
expect.that(response.getStatus()).isEqualTo(200);
expect.that(response.getMessage()).isEqualTo("Success");
// Data validation
UserProfile profile = response.getData();
expect.that(profile).isNotNull();
expect.that(profile.getUserId()).isEqualTo(userId);
expect.that(profile.getUsername()).isNotEmpty();
expect.that(profile.getCreatedDate()).isLessThan(Instant.now());
// Optional fields validation
if (profile.getLastLoginDate() != null) {
expect.that(profile.getLastLoginDate()).isAtMost(Instant.now());
}
}Utilities for testing that Truth assertions fail as expected with proper error messages.
/**
* Tests that the given assertion callback fails and returns the AssertionError.
* @param assertionCallback callback containing the assertion that should fail
* @return the AssertionError thrown by the failed assertion
*/
public static AssertionError expectFailure(SimpleSubjectBuilderCallback<?> assertionCallback);
/**
* Tests that the given assertion callback fails when using a custom Subject factory.
* @param factory the Subject factory to use
* @param assertionCallback callback containing the assertion that should fail
* @return the AssertionError thrown by the failed assertion
*/
public static <S extends Subject, A> AssertionError expectFailureAbout(
Subject.Factory<S, A> factory,
SubjectBuilderCallback<S> assertionCallback);
/**
* Functional interface for assertion callbacks.
*/
@FunctionalInterface
public interface SimpleSubjectBuilderCallback<T> {
void invokeAssertion(SimpleSubjectBuilder<?, T> expect);
}
/**
* Functional interface for custom subject assertion callbacks.
*/
@FunctionalInterface
public interface SubjectBuilderCallback<S extends Subject> {
void invokeAssertion(SimpleSubjectBuilder<S, ?> expect);
}Basic Usage Examples:
import static com.google.common.truth.ExpectFailure.expectFailure;
@Test
public void testAssertionFailureMessages() {
// Test that assertion fails with expected message
AssertionError error = expectFailure(
whenTesting -> whenTesting.that("actual").isEqualTo("expected")
);
assertThat(error).hasMessageThat().contains("actual");
assertThat(error).hasMessageThat().contains("expected");
}
@Test
public void testCustomErrorMessage() {
AssertionError error = expectFailure(
whenTesting -> whenTesting.withMessage("Custom error")
.that(42).isEqualTo(24)
);
assertThat(error).hasMessageThat().contains("Custom error");
assertThat(error).hasMessageThat().contains("42");
assertThat(error).hasMessageThat().contains("24");
}
@Test
public void testCollectionAssertionFailure() {
List<String> actual = Arrays.asList("apple", "banana");
List<String> expected = Arrays.asList("apple", "cherry");
AssertionError error = expectFailure(
whenTesting -> whenTesting.that(actual).containsExactlyElementsIn(expected)
);
assertThat(error).hasMessageThat().contains("missing");
assertThat(error).hasMessageThat().contains("cherry");
assertThat(error).hasMessageThat().contains("unexpected");
assertThat(error).hasMessageThat().contains("banana");
}Testing complex assertion failure scenarios and error message formatting.
// Testing numeric comparison failures
@Test
public void testNumericComparisonFailures() {
AssertionError error = expectFailure(
whenTesting -> whenTesting.that(5).isGreaterThan(10)
);
assertThat(error).hasMessageThat().contains("5");
assertThat(error).hasMessageThat().contains("10");
assertThat(error).hasMessageThat().contains("greater than");
}
// Testing floating-point tolerance failures
@Test
public void testToleranceFailures() {
AssertionError error = expectFailure(
whenTesting -> whenTesting.that(1.0).isWithin(0.001).of(2.0)
);
assertThat(error).hasMessageThat().contains("1.0");
assertThat(error).hasMessageThat().contains("2.0");
assertThat(error).hasMessageThat().contains("0.001");
}
// Testing string assertion failures
@Test
public void testStringAssertionFailures() {
AssertionError error = expectFailure(
whenTesting -> whenTesting.that("hello world").matches("\\d+")
);
assertThat(error).hasMessageThat().contains("hello world");
assertThat(error).hasMessageThat().contains("\\d+");
assertThat(error).hasMessageThat().contains("match");
}
// Testing custom subject failure messages
@Test
public void testCustomSubjectFailure() {
// Assuming a custom PersonSubject
Person person = new Person("Alice", 25);
AssertionError error = expectFailureAbout(
PersonSubject.factory(),
whenTesting -> whenTesting.that(person).hasName("Bob")
);
assertThat(error).hasMessageThat().contains("Alice");
assertThat(error).hasMessageThat().contains("Bob");
}Specialized Subject for making assertions about Truth assertion failures and error messages.
/**
* Returns a Subject.Factory for creating TruthFailureSubject instances.
* @return factory for TruthFailureSubject
*/
public static Subject.Factory<TruthFailureSubject, AssertionError> truthFailures();
/**
* Subject for making assertions about Truth assertion failures.
*/
public class TruthFailureSubject extends Subject {
/**
* Returns a StringSubject for making assertions about the failure message.
*/
public StringSubject hasMessageThat();
/**
* Asserts that the failure message contains the given fact key-value pair.
* @param key the fact key
* @param value the fact value
*/
public void factKeys(String... keys);
/**
* Asserts about the facts contained in the failure message.
*/
public void factValue(String key, String value);
}Usage Examples:
import static com.google.common.truth.TruthFailureSubject.truthFailures;
@Test
public void testFailureMessageStructure() {
AssertionError failure = expectFailure(
whenTesting -> whenTesting.that(Arrays.asList(1, 2, 3))
.containsExactly(1, 2, 4)
);
assertThat(failure)
.factKeys()
.contains("missing (1)");
assertThat(failure)
.factKeys()
.contains("unexpected (1)");
assertThat(failure)
.factValue("missing (1)", "4");
assertThat(failure)
.factValue("unexpected (1)", "3");
}Integration utilities for using Truth with JUnit features like assumptions.
/**
* Returns a StandardSubjectBuilder that uses JUnit's assumption mechanism.
* Failed assertions will cause the test to be skipped rather than failed.
* @return StandardSubjectBuilder for JUnit assumptions
*/
public static StandardSubjectBuilder assume();Usage Examples:
import static com.google.common.truth.TruthJUnit.assume;
@Test
public void testThatRequiresSpecificEnvironment() {
// Skip test if not in the expected environment
assume().that(System.getProperty("test.environment")).isEqualTo("integration");
// Skip test if required service is not available
assume().that(serviceHealthCheck.isHealthy()).isTrue();
// Continue with test only if assumptions pass
String result = integrationService.performOperation();
assertThat(result).isEqualTo("expected");
}
@Test
public void testWithOSAssumption() {
// Skip test on Windows
assume().that(System.getProperty("os.name")).doesNotContain("Windows");
// Unix-specific test logic
String command = executeUnixCommand("ls -la");
assertThat(command).contains("total");
}// Custom test rule combining Expect with setup/teardown
public class DatabaseTestRule implements TestRule {
private final Expect expect = Expect.create();
private DatabaseConnection connection;
@Override
public Statement apply(Statement base, Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
connection = setupDatabase();
try {
base.evaluate();
} finally {
expect.checkAndClearFailures(); // Manual failure checking
cleanupDatabase(connection);
}
}
};
}
public Expect expect() {
return expect;
}
}
// Usage in test
public class DatabaseIntegrationTest {
@Rule
public final DatabaseTestRule dbRule = new DatabaseTestRule();
@Test
public void testDatabaseOperations() {
dbRule.expect().that(dbRule.getConnection()).isNotNull();
// Additional database tests using dbRule.expect()
}
}// Using Expect with parameterized tests for comprehensive validation
@RunWith(Parameterized.class)
public class ParameterizedValidationTest {
@Rule
public final Expect expect = Expect.create();
@Parameter
public String input;
@Parameter(1)
public String expectedOutput;
@Parameters
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][] {
{"hello", "HELLO"},
{"world", "WORLD"},
{"test", "TEST"}
});
}
@Test
public void testTransformation() {
String result = transformService.transform(input);
expect.withMessage("Input: %s", input)
.that(result).isEqualTo(expectedOutput);
expect.that(result).hasLength(input.length());
expect.that(result).matches("[A-Z]+");
}
}/**
* JUnit TestRule for collecting assertion failures and reporting them together.
*/
public class Expect implements TestRule {
/**
* Creates a new Expect instance.
*/
public static Expect create();
/**
* Creates assertions that collect failures instead of throwing immediately.
* @param actual the value under test
*/
public <T> Subject that(T actual);
/**
* Adds failure message prefix for subsequent assertions.
* @param message the message to prepend
*/
public Expect withMessage(String message);
/**
* Adds formatted failure message prefix for subsequent assertions.
* @param format format string
* @param args format arguments
*/
public Expect withMessage(String format, Object... args);
/**
* Creates custom subject assertions that collect failures.
* @param factory Subject factory
*/
public <S extends Subject, A> SimpleSubjectBuilder<S, A> about(Subject.Factory<S, A> factory);
}
/**
* Utilities for testing Truth assertion failures.
*/
public class ExpectFailure {
/**
* Tests that an assertion fails and returns the error.
* @param callback assertion that should fail
*/
public static AssertionError expectFailure(SimpleSubjectBuilderCallback<?> callback);
/**
* Tests that a custom subject assertion fails.
* @param factory Subject factory
* @param callback assertion that should fail
*/
public static <S extends Subject, A> AssertionError expectFailureAbout(
Subject.Factory<S, A> factory,
SubjectBuilderCallback<S> callback);
}
/**
* Functional interface for assertion callbacks.
*/
@FunctionalInterface
public interface SimpleSubjectBuilderCallback<T> {
void invokeAssertion(SimpleSubjectBuilder<?, T> expect);
}
/**
* Functional interface for custom subject assertion callbacks.
*/
@FunctionalInterface
public interface SubjectBuilderCallback<S extends Subject> {
void invokeAssertion(SimpleSubjectBuilder<S, ?> expect);
}
/**
* Subject for making assertions about Truth assertion failures.
*/
public class TruthFailureSubject extends Subject {
/**
* Factory for creating TruthFailureSubject instances.
*/
public static Subject.Factory<TruthFailureSubject, AssertionError> truthFailures();
/**
* Returns StringSubject for asserting about failure message.
*/
public StringSubject hasMessageThat();
/**
* Asserts about fact keys in the failure message.
* @param keys expected fact keys
*/
public void factKeys(String... keys);
/**
* Asserts about a specific fact value in the failure message.
* @param key fact key
* @param value expected fact value
*/
public void factValue(String key, String value);
}
/**
* JUnit integration utilities.
*/
public class TruthJUnit {
/**
* Returns StandardSubjectBuilder using JUnit assumption mechanism.
* Failed assertions skip the test instead of failing it.
*/
public static StandardSubjectBuilder assume();
}Install with Tessl CLI
npx tessl i tessl/maven-com-google-truth--truth