diff --git a/core/src/main/java/org/truth0/TestVerb.java b/core/src/main/java/org/truth0/TestVerb.java index f0968ebf4..edc5ac2b1 100644 --- a/core/src/main/java/org/truth0/TestVerb.java +++ b/core/src/main/java/org/truth0/TestVerb.java @@ -19,6 +19,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.List; +import java.util.Map; import org.truth0.subjects.BooleanSubject; import org.truth0.subjects.ClassSubject; @@ -27,6 +28,7 @@ import org.truth0.subjects.IntegerSubject; import org.truth0.subjects.IterableSubject; import org.truth0.subjects.ListSubject; +import org.truth0.subjects.MapSubject; import org.truth0.subjects.StringSubject; import org.truth0.subjects.Subject; @@ -77,4 +79,9 @@ public > ListSubject, T, C> public > ListSubject, T, C> that(T[] target) { return that(Arrays.asList(target)); } + + public > MapSubject, K, V, M> that(Map target) { + return MapSubject.create(getFailureStrategy(), target); + } + } diff --git a/core/src/main/java/org/truth0/subjects/MapSubject.java b/core/src/main/java/org/truth0/subjects/MapSubject.java new file mode 100644 index 000000000..3c2027f61 --- /dev/null +++ b/core/src/main/java/org/truth0/subjects/MapSubject.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2011 David Saff + * Copyright (c) 2011 Christian Gruber + * + * 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 org.truth0.subjects; + +import java.util.Map; + +import org.truth0.FailureStrategy; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.ImmutableList; + +/** + * @author Christian Gruber (cgruber@israfil.net) + */ +@GwtCompatible +public class MapSubject, K, V, M extends Map> extends Subject { + + public MapSubject(FailureStrategy failureStrategy, M map) { + super(failureStrategy, map); + } + + /** + * Attests that the subject holds no objects, or fails. + */ + public void isEmpty() { + if (!getSubject().isEmpty()) { + fail("is empty"); + } + } + + /** + * Attests that the subject holds one or more objects, or fails + */ + public void isNotEmpty() { + if (getSubject().isEmpty()) { + fail("is not empty"); + } + } + + /** + * Attests that the subject contains the provided key or fails. + */ + public WithValue hasKey(final K key) { + if (!getSubject().containsKey(key)) { + fail("has key", key); + } + return new WithValue() { + @Override public void withValue(V expected) { + V actual = getSubject().get(key); + if ((actual == null && key != null) || + !actual.equals(expected)) { + fail("has key/value pair", ImmutableList.of(key, expected), + "actually has key/value pair", ImmutableList.of(key, actual)); + } + } + }; + } + + public void lacksKey(K key) { + if (getSubject().containsKey(key)) { + fail("lacks key", key); + } + } + + public void hasValue(V key) { + if (!getSubject().containsValue(key)) { + fail("has value", key); + } + } + + public void lacksValue(V key) { + if (getSubject().containsValue(key)) { + fail("lacks value", key); + } + } + + public interface WithValue { + void withValue(V value); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public static > MapSubject, K, V, M> create( + FailureStrategy failureStrategy, Map map) { + return new MapSubject(failureStrategy, map); + } + +} diff --git a/core/src/test/java/org/truth0/subjects/MapTest.java b/core/src/test/java/org/truth0/subjects/MapTest.java new file mode 100644 index 000000000..c1b60ce21 --- /dev/null +++ b/core/src/test/java/org/truth0/subjects/MapTest.java @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2011 David Saff + * Copyright (c) 2011 Christian Gruber + * + * 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 org.truth0.subjects; + +import static org.junit.Assert.fail; +import static org.truth0.Truth.ASSERT; + +import java.util.Map; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +import com.google.common.collect.Maps; + +/** + * Tests for Map Subjects. + * + * @author Christian Gruber (cgruber@israfil.net) + */ +@RunWith(JUnit4.class) +public class MapTest { + + @Test public void mapIsEmpty() { + ASSERT.that(map(String.class, String.class)).isEmpty(); + } + + @Test public void mapIsEmptyWithFailure() { + try { + ASSERT.that(map(Integer.class, Integer.class, 1, 5)).isEmpty(); + fail("Should have thrown."); + } catch (AssertionError e) { + ASSERT.that(e.getMessage()).contains("Not true that"); + ASSERT.that(e.getMessage()).contains("is empty"); + } + } + + @Test public void mapIsNotEmpty() { + ASSERT.that(map(Integer.class, Integer.class, 1, 5)).isNotEmpty(); + } + + @Test public void mapIsNotEmptyWithFailure() { + try { + ASSERT.that(map(String.class, String.class)).isNotEmpty(); + fail("Should have thrown."); + } catch (AssertionError e) { + ASSERT.that(e.getMessage()).contains("Not true that"); + ASSERT.that(e.getMessage()).contains("is not empty"); + } + } + + @Test public void mapHasKey() { + ASSERT.that(map(String.class, Object.class, "a", "A")).hasKey("a"); + } + + @Test public void failMapHasKey() { + try { + ASSERT.that(map(String.class, Object.class, "a", "A")).hasKey("b"); + fail("Should have thrown."); + } catch (AssertionError e) { + ASSERT.that(e.getMessage()).contains("Not true that"); + ASSERT.that(e.getMessage()).contains("has key"); + } + } + + @Test public void failMapHasKeyWithNull() { + try { + ASSERT.that(map(String.class, Object.class, "a", "A")).hasKey(null); + fail("Should have thrown."); + } catch (AssertionError e) { + ASSERT.that(e.getMessage()).contains("Not true that"); + ASSERT.that(e.getMessage()).contains("has key "); + } + } + + @Test public void mapLacksKey() { + ASSERT.that(map(String.class, Object.class, "a", "A")).lacksKey("b"); + } + + @Test public void failMapLacksKey() { + try { + ASSERT.that(map(String.class, Object.class, "a", "A")).lacksKey("a"); + fail("Should have thrown."); + } catch (AssertionError e) { + ASSERT.that(e.getMessage()).contains("Not true that"); + ASSERT.that(e.getMessage()).contains("lacks key"); + } + } + + @Test public void mapHasKeyWithValue() { + ASSERT.that(map(String.class, Object.class, "a", String.class)) + .hasKey("a").withValue(String.class); + } + + @Test public void failMapHasKeyWithValue() { + try { + ASSERT.that(map(String.class, Object.class, "a", String.class)) + .hasKey("a").withValue(Integer.class); + fail("Should have thrown."); + } catch (AssertionError e) { + ASSERT.that(e.getMessage()).contains("Not true that"); + ASSERT.that(e.getMessage()).contains("has key/value pair"); + } + } + + @Test public void mapHasValue() { + ASSERT.that(map(String.class, Object.class, "a", "A")).hasValue("A"); + } + + @Test public void mapHasValueWithNull() { + ASSERT.that(map(String.class, Object.class, "a", null)).hasValue(null); + } + + @Test public void failMapHasValue() { + try { + ASSERT.that(map(String.class, Object.class, "a", "A")).hasValue("B"); + fail("Should have thrown."); + } catch (AssertionError e) { + ASSERT.that(e.getMessage()).contains("Not true that"); + ASSERT.that(e.getMessage()).contains("has value"); + } + } + + @Test public void mapLacksValue() { + ASSERT.that(map(String.class, Object.class, "a", "A")).lacksValue("B"); + } + + @Test public void failMapLacksValue() { + try { + ASSERT.that(map(String.class, Object.class, "a", "A")).lacksValue("A"); + fail("Should have thrown."); + } catch (AssertionError e) { + ASSERT.that(e.getMessage()).contains("Not true that"); + ASSERT.that(e.getMessage()).contains("lacks value"); + } + } + + + @SuppressWarnings("unchecked") // Want this to blow up if wrong. + public static Map map(Class keyClass, Class valueClass, Object ... keyval) { + Map map = Maps.newHashMap(); + if (keyval.length % 2 != 0) + throw new IllegalArgumentException("Wrong number of key/value pairs."); + for (int i = 0; i < keyval.length ; i = i + 2) { + map.put(keyClass.cast(keyval[i]), valueClass.cast(keyval[i + 1])); + } + return map; + } +}