/* * Copyright (c) 2011 Google, Inc. * * 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. */ package com.google.common.truth; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.fail; import com.google.auto.value.AutoValue; import com.google.common.base.Optional; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableListMultimap; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableMultiset; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSetMultimap; import com.google.common.collect.ImmutableSortedMap; import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.ImmutableTable; import com.google.common.collect.Iterators; import com.google.common.testing.NullPointerTester; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.math.BigDecimal; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; /** * Tests for generic Subject behavior. * * @author David Saff * @author Christian Gruber */ @RunWith(JUnit4.class) public class SubjectTest { @Test public void nullPointerTester() { NullPointerTester npTester = new NullPointerTester(); // TODO(kak): Automatically generate this list with reflection, // or maybe use AbstractPackageSanityTests? npTester.testAllPublicInstanceMethods(assertThat(BigDecimal.TEN)); npTester.testAllPublicInstanceMethods(assertThat(false)); npTester.testAllPublicInstanceMethods(assertThat(String.class)); npTester.testAllPublicInstanceMethods(assertThat((Comparable<String>) "hello")); npTester.testAllPublicInstanceMethods(assertThat(2d)); npTester.testAllPublicInstanceMethods(assertThat(2f)); npTester.testAllPublicInstanceMethods(assertThat(Optional.absent())); npTester.testAllPublicInstanceMethods(assertThat(1)); npTester.testAllPublicInstanceMethods(assertThat(ImmutableList.of())); npTester.testAllPublicInstanceMethods(assertThat(ImmutableListMultimap.of())); npTester.testAllPublicInstanceMethods(assertThat(1L)); npTester.testAllPublicInstanceMethods(assertThat(ImmutableMap.of())); npTester.testAllPublicInstanceMethods(assertThat(ImmutableMultimap.of())); npTester.testAllPublicInstanceMethods(assertThat(ImmutableMultiset.of())); npTester.testAllPublicInstanceMethods(assertThat(new Object[0])); npTester.testAllPublicInstanceMethods(assertThat(ImmutableSetMultimap.of())); npTester.testAllPublicInstanceMethods(assertThat(ImmutableSortedMap.of())); npTester.testAllPublicInstanceMethods(assertThat(ImmutableSortedSet.of())); npTester.testAllPublicInstanceMethods(assertThat("hello")); npTester.testAllPublicInstanceMethods(assertThat(new Object())); npTester.testAllPublicInstanceMethods(assertThat(ImmutableTable.of())); npTester.testAllPublicInstanceMethods(assertThat(new Exception())); } @Test public void allAssertThatOverloadsAcceptNull() throws Exception { NullPointerTester npTester = new NullPointerTester(); for (Method method : Truth.class.getDeclaredMethods()) { if (Modifier.isPublic(method.getModifiers()) && method.getName().equals("assertThat") && method.getParameterTypes().length == 1) { Object actual = null; Subject<?, ?> subject = (Subject<?, ?>) method.invoke(Truth.class, actual); subject.isNull(); try { subject.isNotNull(); // should throw fail("assertThat(null).isNotNull() should throw an exception!"); } catch (AssertionError expected) { assertThat(expected) .hasMessageThat() .isEqualTo("Not true that the subject is a non-null reference"); } subject.isSameAs(null); subject.isNotSameAs(new Object()); subject.isNotIn(ImmutableList.<Object>of()); subject.isNoneOf(new Object(), new Object()); // This is a hack...but we have to skip DoubleSubject (requires a tolerance) // and array-based subjects (they require a primitive array for the actual value). if (subject instanceof DoubleSubject || subject instanceof AbstractArraySubject) { continue; } // check all public assertion methods for correct null handling npTester.testAllPublicInstanceMethods(subject); subject.isNotEqualTo(new Object()); subject.isEqualTo(null); try { subject.isEqualTo(new Object()); // should throw fail("assertThat(null).isEqualTo(<non-null>) should throw an exception!"); } catch (AssertionError expected) { assertThat(expected).hasMessageThat().contains("Not true that "); assertThat(expected).hasMessageThat().contains(" is equal to "); } } } } private static final Object OBJECT_1 = new Object() { @Override public String toString() { return "Object 1"; } }; private static final Object OBJECT_2 = new Object() { @Override public String toString() { return "Object 2"; } }; @Test public void toStringsAreIdentical() { IntWrapper wrapper = new IntWrapper(); wrapper.wrapped = 5; try { assertThat(5).isEqualTo(wrapper); fail("Should have thrown."); } catch (AssertionError expected) { assertThat(expected) .hasMessageThat() .isEqualTo( "Not true that <5> (java.lang.Integer) " + "is equal to <5> (com.google.common.truth.SubjectTest$IntWrapper)"); } } private static class IntWrapper { int wrapped; @Override public String toString() { return Integer.toString(wrapped); } } @Test public void isSameAsWithNulls() { Object o = null; assertThat(o).isSameAs(null); } @Test public void isSameAsFailureWithNulls() { Object o = null; try { assertThat(o).isSameAs("a"); fail("Should have thrown."); } catch (AssertionError e) { assertThat(e).hasMessageThat().isEqualTo("Not true that <null> is the same instance as <a>"); } } @Test public void isSameAsWithSameObject() { Object a = new Object(); Object b = a; assertThat(a).isSameAs(b); } @Test public void isSameAsFailureWithObjects() { Object a = OBJECT_1; Object b = OBJECT_2; try { assertThat(a).isSameAs(b); fail("Should have thrown."); } catch (AssertionError e) { assertThat(e) .hasMessageThat() .isEqualTo("Not true that <Object 1> is the same instance as <Object 2>"); } } @Test public void isSameAsFailureWithComparableObjects() { Object a = "ab"; Object b = new StringBuilder("ab").toString(); try { assertThat(a).isSameAs(b); fail("Should have thrown."); } catch (AssertionError e) { assertThat(e) .hasMessageThat() .isEqualTo( "Not true that <ab> is the same instance as <ab>" + " (although their toString() representations are the same)"); } } @Test public void isSameAsFailureWithDifferentTypesAndSameToString() { Object a = "true"; Object b = true; try { assertThat(a).isSameAs(b); fail("Should have thrown."); } catch (AssertionError e) { assertThat(e) .hasMessageThat() .isEqualTo( "Not true that <true> (java.lang.String) is the same" + " instance as <true> (java.lang.Boolean)"); } } @Test public void isNotSameAsWithNulls() { Object o = null; assertThat(o).isNotSameAs("a"); } @Test public void isNotSameAsFailureWithNulls() { Object o = null; try { assertThat(o).isNotSameAs(null); fail("Should have thrown."); } catch (AssertionError e) { assertThat(e) .hasMessageThat() .isEqualTo("Not true that <null> is not the same instance as <null>"); } } @Test public void isNotSameAsWithObjects() { Object a = new Object(); Object b = new Object(); assertThat(a).isNotSameAs(b); } @Test public void isNotSameAsFailureWithSameObject() { Object a = OBJECT_1; Object b = a; try { assertThat(a).isNotSameAs(b); fail("Should have thrown."); } catch (AssertionError e) { assertThat(e) .hasMessageThat() .isEqualTo("Not true that <Object 1> is not the same instance as <Object 1>"); } } @Test public void isNotSameAsWithComparableObjects() { Object a = "ab"; Object b = new StringBuilder("ab").toString(); assertThat(a).isNotSameAs(b); } @Test public void isNotSameAsWithDifferentTypesAndSameToString() { Object a = "true"; Object b = true; assertThat(a).isNotSameAs(b); } @Test public void isNull() { Object o = null; assertThat(o).isNull(); } @Test public void isNullFail() { Object o = new Object(); try { assertThat(o).isNull(); fail("Should have thrown."); } catch (AssertionError e) { assertThat(e).hasMessageThat().isEqualTo("Not true that <" + o.toString() + "> is null"); } } @Test public void stringIsNullFail() { try { assertThat("foo").isNull(); fail("Should have thrown."); } catch (AssertionError e) { assertThat(e).hasMessageThat().isEqualTo("Not true that <\"foo\"> is null"); } } @Test public void isNotNull() { Object o = new Object(); assertThat(o).isNotNull(); } @Test public void isNotNullFail() { Object o = null; try { assertThat(o).isNotNull(); fail("Should have thrown."); } catch (AssertionError e) { assertThat(e).hasMessageThat().isEqualTo("Not true that the subject is a non-null reference"); } } @Test public void isEqualToWithNulls() { Object o = null; assertThat(o).isEqualTo(null); } @Test public void isEqualToFailureWithNulls() { Object o = null; try { assertThat(o).isEqualTo("a"); fail("Should have thrown."); } catch (AssertionError e) { assertThat(e).hasMessageThat().isEqualTo("Not true that <null> is equal to <a>"); } } @Test public void isEqualToWithSameObject() { Object a = new Object(); Object b = a; assertThat(a).isEqualTo(b); } @Test public void isEqualToFailureWithObjects() { Object a = OBJECT_1; Object b = OBJECT_2; try { assertThat(a).isEqualTo(b); fail("Should have thrown."); } catch (AssertionError e) { assertThat(e).hasMessageThat().isEqualTo("Not true that <Object 1> is equal to <Object 2>"); } } @Test public void isEqualToWithComparableObjects() { Object a = "ab"; Object b = new StringBuilder("ab").toString(); assertThat(a).isEqualTo(b); } @Test public void isEqualToFailureWithComparableObjects() { Object a = "ab"; Object b = new StringBuilder("aa").toString(); try { assertThat(a).isEqualTo(b); fail("Should have thrown."); } catch (AssertionError e) { assertThat(e).hasMessageThat().isEqualTo("Not true that <ab> is equal to <aa>"); } } @Test public void isEqualToFailureWithDifferentTypesAndSameToString() { Object a = "true"; Object b = true; try { assertThat(a).isEqualTo(b); fail("Should have thrown."); } catch (AssertionError e) { assertThat(e) .hasMessageThat() .isEqualTo( "Not true that <true> (java.lang.String) is equal to" + " <true> (java.lang.Boolean)"); } } @Test public void isNotEqualToWithNulls() { Object o = null; assertThat(o).isNotEqualTo("a"); } @Test public void isNotEqualToFailureWithNulls() { Object o = null; try { assertThat(o).isNotEqualTo(null); fail("Should have thrown."); } catch (AssertionError e) { assertThat(e).hasMessageThat().isEqualTo("Not true that <null> is not equal to <null>"); } } @Test public void isNotEqualToWithObjects() { Object a = new Object(); Object b = new Object(); assertThat(a).isNotEqualTo(b); } @Test public void isNotEqualToFailureWithObjects() { Object o = null; try { assertThat(o).isNotEqualTo(null); fail("Should have thrown."); } catch (AssertionError e) { assertThat(e).hasMessageThat().isEqualTo("Not true that <null> is not equal to <null>"); } } @Test public void isNotEqualToFailureWithSameObject() { Object a = OBJECT_1; Object b = a; try { assertThat(a).isNotEqualTo(b); fail("Should have thrown."); } catch (AssertionError e) { assertThat(e) .hasMessageThat() .isEqualTo("Not true that <Object 1> is not equal to <Object 1>"); } } @Test public void isNotEqualToWithComparableObjects() { Object a = "ab"; Object b = new StringBuilder("aa").toString(); assertThat(a).isNotEqualTo(b); } @Test public void isNotEqualToFailureWithComparableObjects() { Object a = "ab"; Object b = new StringBuilder("ab").toString(); try { assertThat(a).isNotEqualTo(b); fail("Should have thrown."); } catch (AssertionError e) { assertThat(e).hasMessageThat().isEqualTo("Not true that <ab> is not equal to <ab>"); } } @Test public void isNotEqualToWithDifferentTypesAndSameToString() { Object a = "true"; Object b = true; assertThat(a).isNotEqualTo(b); } @Test public void isInstanceOf() { assertThat("a").isInstanceOf(String.class); } @Test public void isInstanceOfFail() { try { assertThat(4.5).isInstanceOf(Long.class); fail("Should have thrown."); } catch (AssertionError e) { assertThat(e) .hasMessageThat() .isEqualTo( "Not true that <4.5> is an instance of <java.lang.Long>." + " It is an instance of <java.lang.Double>"); } } @Test public void isNotInstanceOf() { assertThat("a").isNotInstanceOf(Long.class); } @Test public void isNotInstanceOfFail() { try { assertThat(5).isNotInstanceOf(Number.class); fail("Should have thrown."); } catch (AssertionError e) { assertThat(e) .hasMessageThat() .isEqualTo("<5> expected not to be an instance of java.lang.Number, but was."); } } @Test public void isIn() { assertThat("b").isIn(oneShotIterable("a", "b", "c")); } @Test public void isInJustTwo() { assertThat("b").isIn(oneShotIterable("a", "b")); } @Test public void isInFailure() { try { assertThat("x").isIn(oneShotIterable("a", "b", "c")); fail("Should have thrown."); } catch (AssertionError e) { assertThat(e) .hasMessageThat() .isEqualTo("Not true that <\"x\"> is equal to any element in <[a, b, c]>"); } } @Test public void isInNullInListWithNull() { assertThat((String) null).isIn(oneShotIterable("a", "b", (String) null)); } @Test public void isInNonnullInListWithNull() { assertThat("b").isIn(oneShotIterable("a", "b", (String) null)); } @Test public void isInNullFailure() { try { assertThat((String) null).isIn(oneShotIterable("a", "b", "c")); fail("Should have thrown."); } catch (AssertionError e) { assertThat(e) .hasMessageThat() .isEqualTo("Not true that <null> is equal to any element in <[a, b, c]>"); } } @Test public void isInEmptyFailure() { try { assertThat("b").isIn(ImmutableList.<String>of()); fail("Should have thrown."); } catch (AssertionError e) { assertThat(e) .hasMessageThat() .isEqualTo("Not true that <\"b\"> is equal to any element in <[]>"); } } @Test public void isAnyOf() { assertThat("b").isAnyOf("a", "b", "c"); } @Test public void isAnyOfJustTwo() { assertThat("b").isAnyOf("a", "b"); } @Test public void isAnyOfFailure() { try { assertThat("x").isAnyOf("a", "b", "c"); fail("Should have thrown."); } catch (AssertionError e) { assertThat(e) .hasMessageThat() .isEqualTo("Not true that <\"x\"> is equal to any of <[a, b, c]>"); } } @Test public void isAnyOfNullInListWithNull() { assertThat((String) null).isAnyOf("a", "b", (String) null); } @Test public void isAnyOfNonnullInListWithNull() { assertThat("b").isAnyOf("a", "b", (String) null); } @Test public void isAnyOfNullFailure() { try { assertThat((String) null).isAnyOf("a", "b", "c"); fail("Should have thrown."); } catch (AssertionError e) { assertThat(e) .hasMessageThat() .isEqualTo("Not true that <null> is equal to any of <[a, b, c]>"); } } @Test public void isNotIn() { assertThat("x").isNotIn(oneShotIterable("a", "b", "c")); } @Test public void isNotInFailure() { try { assertThat("b").isNotIn(oneShotIterable("a", "b", "c")); fail("Should have thrown."); } catch (AssertionError e) { assertThat(e) .hasMessageThat() .isEqualTo("Not true that <\"b\"> is not in [a, b, c]. It was found at index 1"); } } @Test public void isNotInNull() { assertThat((String) null).isNotIn(oneShotIterable("a", "b", "c")); } @Test public void isNotInNullFailure() { try { assertThat((String) null).isNotIn(oneShotIterable("a", "b", (String) null)); fail("Should have thrown."); } catch (AssertionError e) { assertThat(e) .hasMessageThat() .isEqualTo("Not true that <null> is not in [a, b, null]. It was found at index 2"); } } @Test public void isNotInEmpty() { assertThat("b").isNotIn(ImmutableList.<String>of()); } @Test public void isNoneOf() { assertThat("x").isNoneOf("a", "b", "c"); } @Test public void isNoneOfFailure() { try { assertThat("b").isNoneOf("a", "b", "c"); fail("Should have thrown."); } catch (AssertionError e) { assertThat(e) .hasMessageThat() .isEqualTo("Not true that <\"b\"> is not in [a, b, c]. It was found at index 1"); } } @Test public void isNoneOfNull() { assertThat((String) null).isNoneOf("a", "b", "c"); } @Test public void isNoneOfNullFailure() { try { assertThat((String) null).isNoneOf("a", "b", (String) null); fail("Should have thrown."); } catch (AssertionError e) { assertThat(e) .hasMessageThat() .isEqualTo("Not true that <null> is not in [a, b, null]. It was found at index 2"); } } @Test public void throwableHasInitedCause() { NullPointerException cause = new NullPointerException(); String msg = "foo"; try { Truth.THROW_ASSERTION_ERROR.fail(msg, cause); } catch (AssertionError expected) { assertThat(expected).hasMessageThat().isEqualTo(msg); assertThat(expected).hasCauseThat().isSameAs(cause); } } @Test @SuppressWarnings("EqualsIncompatibleType") public void equalsThrowsUSOE() { try { boolean unused = assertThat(5).equals(5); } catch (UnsupportedOperationException expected) { assertThat(expected) .hasMessageThat() .isEqualTo("If you meant to test object equality, use .isEqualTo(other) instead."); return; } fail("Should have thrown."); } @Test public void hashCodeThrowsUSOE() { try { int unused = assertThat(5).hashCode(); } catch (UnsupportedOperationException expected) { assertThat(expected).hasMessageThat().isEqualTo("Subject.hashCode() is not supported."); return; } fail("Should have thrown."); } @Test public void checkPersistsStrategy() { try { new DefaultSubject(Truth.THROW_ASSERTION_ERROR, null).check().that("foo").isNull(); } catch (AssertionError e) { assertThat(e).hasMessageThat().isEqualTo("Not true that <\"foo\"> is null"); } } @Test public void ignoreCheckDiscardsFailures() { new DefaultSubject(Truth.THROW_ASSERTION_ERROR, null).ignoreCheck().that("foo").isNull(); } @SafeVarargs private static <T> Iterable<T> oneShotIterable(final T... values) { final Iterator<T> iterator = Iterators.forArray(values); return new Iterable<T>() { @Override public Iterator<T> iterator() { return iterator; } @Override public String toString() { return Arrays.toString(values); } }; } @AutoValue abstract static class Foo { public static Foo create(Collection<Long> nums) { return new AutoValue_SubjectTest_Foo(nums); } abstract Collection<Long> nums(); } @Test public void disambiguationWithSameToString_autovalue() { Foo foo1 = Foo.create(Arrays.asList(1L, 2L)); Foo foo2 = Foo.create(ImmutableSet.of(1L, 2L)); try { assertThat(foo1).isEqualTo(foo2); } catch (AssertionError expected) { assertThat(expected) .hasMessageThat() .isEqualTo( "Not true that <Foo{nums=[1, 2]}> is equal to <Foo{nums=[1, 2]}> " + "(although their toString() representations are the same)"); return; } fail("Should have thrown."); } @Test public void disambiguationWithSameToString_immutableSets() { ImmutableSet<Integer> ints = ImmutableSet.of(1, 2, 3); ImmutableSet<Long> longs = ImmutableSet.of(1L, 2L, 3L); try { assertThat(ints).isEqualTo(longs); } catch (AssertionError expected) { assertThat(expected) .hasMessageThat() .isEqualTo( "Not true that <[1, 2, 3]> is equal to <[1, 2, 3]> " + "(although their toString() representations are the same)"); return; } fail("Should have thrown."); } }