com.fitbur.assertj.api.AutoCloseableSoftAssertions Maven / Gradle / Ivy
/**
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* Copyright 2012-2016 the original author or authors.
*/
package com.fitbur.assertj.api;
/**
* A version of {@link SoftAssertions} that uses try-with-resources statement to automatically call
* {@link SoftAssertions#assertAll()} so that you don't forget to.
*
* Suppose we have a test case and in it we'd like to make numerous assertions. In this case, we're hosting a dinner
* party and we want to ensure not only that all our guests survive but also that nothing in the mansion has been unduly
* disturbed:
*
*
*
* @Test
* public void host_dinner_party_where_nobody_dies() {
* Mansion mansion = new Mansion();
* mansion.hostPotentiallyMurderousDinnerParty();
* assertThat(mansion.guests()).as("Living Guests").isEqualTo(7);
* assertThat(mansion.kitchen()).as("Kitchen").isEqualTo("clean");
* assertThat(mansion.library()).as("Library").isEqualTo("clean");
* assertThat(mansion.revolverAmmo()).as("Revolver Ammo").isEqualTo(6);
* assertThat(mansion.candlestick()).as("Candlestick").isEqualTo("pristine");
* assertThat(mansion.colonel()).as("Colonel").isEqualTo("well kempt");
* assertThat(mansion.professor()).as("Professor").isEqualTo("well kempt");
* }
*
*
*
* After running the test, JUnit provides us with the following exception message:
*
*
*
* org.junit.ComparisonFailure: [Living Guests] expected:<[7]> but was:<[6]>
*
*
*
* Oh no! A guest has been murdered! But where, how, and by whom?
*
*
*
* Unfortunately frameworks like JUnit halt the test upon the first failed assertion. Therefore, to collect more
* evidence, we'll have to rerun the test (perhaps after attaching a debugger or modifying the test to skip past the
* first assertion). Given that hosting dinner parties takes a long time, this seems rather inefficient.
*
*
*
* Instead let's change the test so that at its completion we get the result of all assertions at once. We can do that
* by using a SoftAssertions instance instead of the static methods on {@link Assertions} as follows:
*
*
*
* @Test
* public void host_dinner_party_where_nobody_dies() {
* Mansion mansion = new Mansion();
* mansion.hostPotentiallyMurderousDinnerParty();
* try (AutoCloseableSoftAssertions softly = new AutoCloseableSoftAssertions()) {
* softly.assertThat(mansion.guests()).as("Living Guests").isEqualTo(7);
* softly.assertThat(mansion.kitchen()).as("Kitchen").isEqualTo("clean");
* softly.assertThat(mansion.library()).as("Library").isEqualTo("clean");
* softly.assertThat(mansion.revolverAmmo()).as("Revolver Ammo").isEqualTo(6);
* softly.assertThat(mansion.candlestick()).as("Candlestick").isEqualTo("pristine");
* softly.assertThat(mansion.colonel()).as("Colonel").isEqualTo("well kempt");
* softly.assertThat(mansion.professor()).as("Professor").isEqualTo("well kempt");
* // no need to call assertAll, it is done when softly is closed.
* }
* }
*
*
*
* Now upon running the test our JUnit exception message is far more detailed:
*
*
*
* com.fitbur.assertj.api.SoftAssertionError: The following 4 assertions failed:
* 1) [Living Guests] expected:<[7]> but was:<[6]>
* 2) [Library] expected:<'[clean]'> but was:<'[messy]'>
* 3) [Candlestick] expected:<'[pristine]'> but was:<'[bent]'>
* 4) [Professor] expected:<'[well kempt]'> but was:<'[bloodied and disheveled]'>
*
*
*
* Aha! It appears that perhaps the Professor used the candlestick to perform the nefarious deed in the library. We
* should let the police take it from here.
*
*
*
* SoftAssertions works by providing you with proxies of the AssertJ assertion objects (those created by
* {@link Assertions}#assertThat...) whose assertion failures are caught and stored. Only when you call
* {@link AutoCloseableSoftAssertions#assertAll()} will a {@link SoftAssertionError} be thrown containing the error
* messages of those previously caught assertion failures.
*
*
*
* Note that because SoftAssertions is stateful you should use a new instance of SoftAssertions per test method. Also,
* if you forget to use try-with-resources statement, the test will pass even if any assertion objects
* threw exceptions (because they're proxied, remember?). So don't forget.
*
*
*
* It is recommended to use {@link AbstractAssert#as(String, Object...)} so that the multiple failed assertions can be
* easily distinguished from one another.
*
*
* @author Brian Laframboise
*
* @see http://beust.com/weblog/2012/07/29/reinventing-assertions/ for the inspiration
*/
public class AutoCloseableSoftAssertions extends SoftAssertions implements AutoCloseable {
@Override
public void close() throws SoftAssertionError {
assertAll();
}
}