001/**
002 * Copyright (C) 2006-2021 Talend Inc. - www.talend.com
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.talend.sdk.component.junit;
017
018import static org.junit.Assert.fail;
019
020import java.util.function.Consumer;
021
022import org.junit.rules.TestRule;
023import org.junit.runner.Description;
024import org.junit.runners.model.Statement;
025
026/**
027 * A rule to access an exception from a test using a {@link Consumer}
028 * Usage example :
029 * 
030 * <pre>
031 * {@code
032 * Rule public ExceptionVerifier<HttpException> httpExceptionRule = new ExceptionVerifier<>();
033 *  &#64;Test
034 *  public void test(){
035 *      httpExceptionRule.assertWith(e -> {
036 *          assertEquals(401, e.getResponse().status());
037 *          assertEquals("expected error message", e.getResponse().error(String.class));
038 *      });
039 *  }
040 * }
041 * </pre>
042 */
043public class ExceptionVerifier<T extends RuntimeException> implements TestRule {
044
045    private Consumer<T> consumer;
046
047    public void assertWith(final Consumer<T> consumer) {
048        this.consumer = consumer;
049    }
050
051    @Override
052    public Statement apply(final Statement base, final Description description) {
053
054        return new Statement() {
055
056            @Override
057            public void evaluate() throws Throwable {
058                try {
059                    base.evaluate();
060                    if (consumer != null) {
061                        fail("expected exception not thrown");
062                    }
063                } catch (final RuntimeException e) {
064                    if (consumer == null) {
065                        throw e;
066                    }
067                    try {
068                        consumer.accept((T) e);
069                    } catch (final ClassCastException cce) {
070                        throw e;
071                    }
072                } finally {
073                    consumer = null;
074                }
075            }
076        };
077    }
078}