Permalink
Browse files

Add a CheckedProviders class

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=130319606
  • Loading branch information...
eatnumber1 authored and sameb committed Jul 26, 2016
1 parent 3468051 commit 801d90f196ee16294696a499070dfe2d9a996265
View
@@ -120,6 +120,7 @@
<pathelement location="lib/build/guava-testlib-19.0.jar"/>
<pathelement location="lib/build/junit.jar"/>
<pathelement location="lib/build/servlet-api-2.5.jar"/>
<pathelement location="lib/build/truth-0.29.jar"/>
<pathelement location="lib/build/easymock.jar"/>
<pathelement location="lib/build/javax.inject-tck.jar"/>
<pathelement location="lib/build/bnd-0.0.384.jar"/>
@@ -4,10 +4,23 @@
<import file="../../common.xml"/>
<target name="compile" description="Compile Java source." depends="common.compile">
<!--
Build the throwingproviders extension using an ant subtask. This could be
accomplished using either the "include" [1] directive, or extension points [2],
but both were introduced in Ant 1.8 and we're using ant 1.6. This does
mean that we will compile guice-throwingproviders twice.
[1]: https://ant.apache.org/manual/Tasks/include.html
[2]: https://ant.apache.org/manual/targets.html#extension-points
-->
<ant antfile="../throwingproviders/build.xml" target="compile"/>
</target>
<path id="compile.classpath">
<fileset dir="${lib.dir}" includes="*.jar"/>
<fileset dir="${lib.dir}/build" includes="*.jar"/>
<pathelement path="../../build/classes"/>
<pathelement path="../throwingproviders/build/classes"/>
</path>
<target name="jar" depends="compile, manifest" description="Build jar.">
View
@@ -25,4 +25,15 @@
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.google.truth</groupId>
<artifactId>truth</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,89 @@
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("Impossible, I hope...", 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...");
}
}
@@ -0,0 +1,142 @@
package com.google.inject.testing.throwingproviders;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.fail;
import com.google.common.truth.FailureStrategy;
import com.google.inject.throwingproviders.CheckedProvider;
import com.google.inject.throwingproviders.CheckedProviders;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/**
* Unit tests for {@link CheckedProviderSubject}.
*
* @author eatnumber1@google.com (Russ Harmon)
*/
@RunWith(JUnit4.class)
public class CheckedProviderSubjectTest {
private static final class FailureStrategyException extends RuntimeException {
FailureStrategyException() {}
FailureStrategyException(String message, Throwable cause) {
super(message, cause);
}
}
private static final class ThrowingFailureStrategy extends FailureStrategy {
@Override
public void fail(String message, Throwable cause) {
throw new FailureStrategyException(message, cause);
}
}
private interface StringCheckedProvider extends CheckedProvider<String> {}
@Test
public void providedValue_gotExpected_expectSuccess() {
String expected = "keep Summer safe";
CheckedProvider<String> provider = CheckedProviders.of(StringCheckedProvider.class, expected);
createSubject(provider).providedValue().isEqualTo(expected);
}
@Test
public void providedValue_gotUnexpected_expectFailure() {
String expected = "keep Summer safe";
String unexpected = "Summer is unsafe";
CheckedProvider<String> provider = CheckedProviders.of(StringCheckedProvider.class, unexpected);
String message =
String.format(
"value provided by <%s>: Not true that <%s> is equal to <%s>",
getReturningProviderName(unexpected), unexpected, expected);
try {
createSubject(provider).providedValue().isEqualTo(expected);
fail("Expected an exception to be thrown");
} catch (FailureStrategyException e) {
assertThat(e).hasMessage(message);
}
}
private static final class SummerException extends RuntimeException {}
@Test
public void providedValue_throws_expectFailure() {
CheckedProvider<?> provider =
CheckedProviders.throwing(StringCheckedProvider.class, SummerException.class);
String message =
String.format(
"checked provider <%s> threw an exception",
getThrowingProviderName(SummerException.class.getName()));
try {
createSubject(provider).providedValue();
fail("Expected an exception to be thrown");
} catch (FailureStrategyException e) {
assertThat(e.getCause()).isInstanceOf(SummerException.class);
assertThat(e).hasMessage(message);
}
}
@Test
public void thrownException_threwExpected_expectSuccess() {
CheckedProvider<?> provider =
CheckedProviders.throwing(StringCheckedProvider.class, SummerException.class);
createSubject(provider).thrownException().isInstanceOf(SummerException.class);
}
@Test
public void thrownException_threwUnexpected_expectFailure() {
Class<? extends Throwable> expected = SummerException.class;
Class<? extends Throwable> unexpected = UnsupportedOperationException.class;
CheckedProvider<?> provider =
CheckedProviders.throwing(StringCheckedProvider.class, unexpected);
String message =
String.format(
"exception thrown by <%s>: Not true that <%s> is an instance of <%s>. "
+ "It is an instance of <%s>",
getThrowingProviderName(UnsupportedOperationException.class.getName()),
UnsupportedOperationException.class.getName(),
SummerException.class.getName(),
UnsupportedOperationException.class.getName());
try {
createSubject(provider).thrownException().isInstanceOf(expected);
fail("Expected an exception to be thrown");
} catch (FailureStrategyException e) {
assertThat(e).hasMessage(message);
}
}
@Test
public void thrownException_gets_expectFailure() {
String getValue = "keep WINTER IS COMING safe";
CheckedProvider<?> provider = CheckedProviders.of(StringCheckedProvider.class, getValue);
String message =
String.format(
"Not true that <%s> threw <an exception>. It provided <%s>",
getReturningProviderName(getValue), getValue);
try {
createSubject(provider).thrownException();
fail("Expected an exception to be thrown");
} catch (FailureStrategyException e) {
assertThat(e).hasMessage(message);
}
}
private <T, P extends CheckedProvider<T>> CheckedProviderSubject<T, P> createSubject(P provider) {
return new CheckedProviderSubject<>(new ThrowingFailureStrategy(), provider);
}
private String getReturningProviderName(String providing) {
return String.format("generated CheckedProvider returning <%s>", providing);
}
private String getThrowingProviderName(String throwing) {
return String.format("generated CheckedProvider throwing <%s>", throwing);
}
}
@@ -25,4 +25,15 @@
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.google.truth</groupId>
<artifactId>truth</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
</dependency>
</dependencies>
</project>
Oops, something went wrong.

0 comments on commit 801d90f

Please sign in to comment.