package com.google.inject.testing.throwingproviders; import static com.google.common.truth.Truth.assertAbout; import com.google.common.annotations.VisibleForTesting; import com.google.common.truth.FailureStrategy; import com.google.common.truth.Subject; import com.google.common.truth.SubjectFactory; import com.google.common.truth.TestVerb; import com.google.common.truth.ThrowableSubject; import com.google.inject.throwingproviders.CheckedProvider; import javax.annotation.Nullable; /** * Truth {@link Subject} for use with {@link CheckedProvider} classes. * * @author eatnumber1@google.com (Russ Harmon) */ public final class CheckedProviderSubject<T, P extends CheckedProvider<T>> extends Subject<CheckedProviderSubject<T, P>, P> { private static final class CheckedProviderSubjectFactory<T, P extends CheckedProvider<T>> extends SubjectFactory<CheckedProviderSubject<T, P>, P> { @Override public CheckedProviderSubject<T, P> getSubject( FailureStrategy failureStrategy, @Nullable P target) { return new CheckedProviderSubject<T, P>(failureStrategy, target); } } private final TestVerb assertVerb; @VisibleForTesting CheckedProviderSubject(FailureStrategy failureStrategy, @Nullable P subject) { super(failureStrategy, subject); this.assertVerb = new TestVerb(failureStrategy); } private TestVerb assert_() { return assertVerb; } public static <T, P extends CheckedProvider<T>> CheckedProviderSubject<T, P> assertThat( @Nullable P provider) { return assertAbout(new CheckedProviderSubjectFactory<T, P>()).that(provider); } /** * Allows for assertions on the value provided by this provider. * * <p>The value provided by a checked provider is the object returned by a call to {@link * CheckedProvider#get} * * @return a {@link Subject} for asserting against the return value of {@link CheckedProvider#get} */ public Subject<?, Object> providedValue() { P provider = getSubject(); T got; try { got = provider.get(); } catch (Exception e) { failureStrategy.fail(String.format("checked provider <%s> threw an exception", provider), e); throw new AssertionError(e); } return assert_().withFailureMessage("value provided by <%s>", provider).that(got); } /** * Allows for assertions on the exception thrown by this provider. * * <p>The exception thrown by a checked provider is the {@link Throwable} thrown by a call to * {@link CheckedProvider#get} * * @return a {@link ThrowableSubject} for asserting against the {@link Throwable} thrown by {@link * CheckedProvider#get} */ public ThrowableSubject thrownException() { P provider = getSubject(); T got; try { got = provider.get(); } catch (Throwable e) { return assert_().withFailureMessage("exception thrown by <%s>", provider).that(e); } failWithBadResults("threw", "an exception", "provided", got); throw new AssertionError("Impossible, I hope..."); } }