com.fitbur.assertj.api.BDDSoftAssertions 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;
import static com.fitbur.assertj.groups.Properties.extractProperty;
import java.util.List;
/**
*
* Suppose we have a test case and in it we'd like to make numerous BDD 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();
* then(mansion.guests()).as("Living Guests").isEqualTo(7);
* then(mansion.kitchen()).as("Kitchen").isEqualTo("clean");
* then(mansion.library()).as("Library").isEqualTo("clean");
* then(mansion.revolverAmmo()).as("Revolver Ammo").isEqualTo(6);
* then(mansion.candlestick()).as("Candlestick").isEqualTo("pristine");
* then(mansion.colonel()).as("Colonel").isEqualTo("well kempt");
* then(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 BDDSoftAssertions instance instead of the static methods on {@link BDDAssertions} as follows:
*
@Test
* public void host_dinner_party_where_nobody_dies() {
* Mansion mansion = new Mansion();
* mansion.hostPotentiallyMurderousDinnerParty();
* BDDSoftAssertions softly = new BDDSoftAssertions();
* softly.then(mansion.guests()).as("Living Guests").isEqualTo(7);
* softly.then(mansion.kitchen()).as("Kitchen").isEqualTo("clean");
* softly.then(mansion.library()).as("Library").isEqualTo("clean");
* softly.then(mansion.revolverAmmo()).as("Revolver Ammo").isEqualTo(6);
* softly.then(mansion.candlestick()).as("Candlestick").isEqualTo("pristine");
* softly.then(mansion.colonel()).as("Colonel").isEqualTo("well kempt");
* softly.then(mansion.professor()).as("Professor").isEqualTo("well kempt");
* softly.assertAll();
* }
*
*
* 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.
*
*
*
* BDDSoftAssertions works by providing you with proxies of the AssertJ assertion objects (those created by
* {@link BDDAssertions}#then...) whose assertion failures are caught and stored. Only when you call
* {@link BDDSoftAssertions#assertAll()} will a {@link SoftAssertionError} be thrown containing the error messages of
* those previously caught assertion failures.
*
*
*
* Note that because BDDSoftAssertions is stateful you should use a new instance of BDDSoftAssertions per test method.
* Also, if you forget to call assertAll() at the end of your test, the test will pass even if any
* assertion objects threw exceptions (because they're proxied, remember?). So don't forget. You might use
* {@link JUnitBDDSoftAssertions} or {@link AutoCloseableBDDSoftAssertions} to get assertAll() to be called
* automatically.
*
*
*
* 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 Reinventing assertions for the
* inspiration
*/
public class BDDSoftAssertions extends AbstractBDDSoftAssertions {
/**
* Verifies that no proxied assertion methods have failed.
*
* @throws SoftAssertionError if any proxied assertion objects threw
*/
public void assertAll() {
List errors = errorsCollected();
if (!errors.isEmpty()) throw new SoftAssertionError(extractProperty("message", String.class).from(errors));
}
}