如何利用Hamcrest简化subtract方法的列表对比测试代码?
Absolutely! Hamcrest was built to make test assertions more readable and cut down on boilerplate code—let’s walk through exactly how to clean up your test case.
First: Simplify the Actual Results Collection
Instead of manually instantiating a List<Double> and adding results one by one, you can use Java Streams to generate your results list in a concise, declarative way. This eliminates repetitive add() calls entirely:
@Test public void verifySubtractWillReturnCorrectValues() { // Generate results using streams to avoid manual list population List<Double> results = Stream.of( new double[]{5.0, 3.0}, // subtract(5.0, 3.0) new double[]{10.0, 2.5}, // subtract(10.0, 2.5) new double[]{0.0, 0.0}, // subtract(0.0, 0.0) new double[]{4.2, 6.1} // subtract(4.2, 6.1) ).map(params -> subtract(params[0], params[1])) .collect(Collectors.toList());
Second: Ditch the Separate Expected List (Use Hamcrest Matchers Directly)
Hamcrest’s contains() matcher lets you define your expected values directly in the assertion statement—no need to create a second List<Double> for expected results. This makes the test’s intent immediately clear to anyone reading it.
For exact matches (note: be cautious with floating points—more on that below):
// Assert with Hamcrest's contains() matcher assertThat(results, contains(2.0, 7.5, 0.0, -1.9)); }
Handle Floating Point Precision
Floating point calculations often have tiny precision errors, so exact equality checks can lead to flaky tests. Hamcrest’s closeTo() matcher solves this by allowing a small tolerance range:
import static org.hamcrest.Matchers.closeTo; import static org.hamcrest.Matchers.contains; import static org.hamcrest.MatcherAssert.assertThat; // ... assertThat(results, contains( closeTo(2.0, 0.001), // Exact value ± 0.001 closeTo(7.5, 0.001), closeTo(0.0, 0.001), closeTo(-1.9, 0.001) ));
Go Even Further: Combine Everything into One Statement
You can eliminate the results variable entirely by generating and asserting in a single step, making the test super concise and focused:
@Test public void verifySubtractWillReturnCorrectValues() { assertThat( Stream.of( new double[]{5.0, 3.0}, new double[]{10.0, 2.5}, new double[]{0.0, 0.0}, new double[]{4.2, 6.1} ).map(params -> subtract(params[0], params[1])) .collect(Collectors.toList()), contains( closeTo(2.0, 0.001), closeTo(7.5, 0.001), closeTo(0.0, 0.001), closeTo(-1.9, 0.001) ) ); }
Key Takeaways
- Eliminate boilerplate: Streams replace tedious manual list population.
- Improve readability: Hamcrest matchers make assertions read like natural language.
- Avoid flaky tests: Use
closeTo()for reliable floating point comparisons.
内容的提问来源于stack exchange,提问作者Nate Thompson

