001 /* 002 * Created on Jan 23, 2008 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 005 * the License. You may obtain a copy of the License at 006 * 007 * http://www.apache.org/licenses/LICENSE-2.0 008 * 009 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 010 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 011 * specific language governing permissions and limitations under the License. 012 * 013 * Copyright @2008-2009 the original author or authors. 014 */ 015 package org.fest.assertions; 016 017 import static org.fest.assertions.Formatting.inBrackets; 018 import static org.fest.util.Strings.concat; 019 import static org.fest.util.Strings.quote; 020 021 import java.util.ArrayList; 022 import java.util.Collection; 023 import java.util.List; 024 import java.util.Map; 025 026 import org.fest.util.Maps; 027 028 /** 029 * Understands assertions for <code>{@link Map}</code>s. To create a new instance of this class use the method 030 * <code>{@link Assertions#assertThat(Map)}</code>. 031 * 032 * @author David DIDIER 033 * @author Yvonne Wang 034 * @author Alex Ruiz 035 */ 036 public class MapAssert extends GroupAssert<Map<?, ?>> { 037 038 private static final String ENTRY = "entry"; 039 private static final String ENTRIES= "entries"; 040 041 /** 042 * Creates a new </code>{@link MapAssert}</code>. 043 * @param actual the target to verify. 044 */ 045 protected MapAssert(Map<?, ?> actual) { 046 super(actual); 047 } 048 049 /** {@inheritDoc} */ 050 public MapAssert as(String description) { 051 description(description); 052 return this; 053 } 054 055 /** {@inheritDoc} */ 056 public MapAssert describedAs(String description) { 057 return as(description); 058 } 059 060 /** {@inheritDoc} */ 061 public MapAssert as(Description description) { 062 description(description); 063 return this; 064 } 065 066 /** {@inheritDoc} */ 067 public MapAssert describedAs(Description description) { 068 return as(description); 069 } 070 071 072 /** 073 * Verifies that the actual <code>{@link Map}</code> contains the given entries. 074 * <p> 075 * Example: 076 * <pre> 077 * // static import org.fest.assertions.Assertions.*; 078 * // static import org.fest.assertions.MapAssert.*; 079 * 080 * assertThat(myMap).{@link #includes(org.fest.assertions.MapAssert.Entry...) includes}({@link #entry(Object, Object) entry}("jedi", yoda), {@link #entry(Object, Object) entry}("sith", anakin)); 081 * </pre> 082 * </p> 083 * @param entries the given entries. 084 * @return this assertion error. 085 * @throws AssertionError if the actual map is <code>null</code>. 086 * @throws AssertionError if the actual <code>Map</code> does not contain any of the given entries. 087 * @throws NullPointerException if the given array of entries is <code>null</code>. 088 * @throws NullPointerException if any of the entries in the given array is <code>null</code>. 089 */ 090 public MapAssert includes(Entry...entries) { 091 isNotNull(); 092 validate(ENTRIES, entries); 093 List<Entry> notFound = new ArrayList<Entry>(); 094 for (Entry e : entries) if (!containsEntry(e)) notFound.add(e); 095 if (!notFound.isEmpty()) failIfNotFound(entryOrEntries(notFound), notFound); 096 return this; 097 } 098 099 /** 100 * Verifies that the actual <code>{@link Map}</code> does not contain the given entries. 101 * <p> 102 * Example: 103 * <pre> 104 * // static import org.fest.assertions.Assertions.*; 105 * // static import org.fest.assertions.MapAssert.*; 106 * 107 * assertThat(myMap).{@link #excludes(org.fest.assertions.MapAssert.Entry...) excludes}({@link #entry(Object, Object) entry}("jedi", yoda), {@link #entry(Object, Object) entry}("sith", anakin)); 108 * </pre> 109 * </p> 110 * @param entries the given entries. 111 * @return this assertion error. 112 * @throws AssertionError if the actual map is <code>null</code>. 113 * @throws AssertionError if the actual <code>Map</code> contains any of the given entries. 114 * @throws NullPointerException if the given array of entries is <code>null</code>. 115 * @throws NullPointerException if any of the entries in the given array is <code>null</code>. 116 */ 117 public MapAssert excludes(Entry...entries) { 118 isNotNull(); 119 validate(ENTRIES, entries); 120 List<Entry> found = new ArrayList<Entry>(); 121 for (Entry e : entries) if (containsEntry(e)) found.add(e); 122 if (!found.isEmpty()) failIfFound(entryOrEntries(found), found); 123 return this; 124 } 125 126 private boolean containsEntry(Entry e) { 127 if (e == null) 128 throw new NullPointerException(formattedErrorMessage("Entries to check should not contain null")); 129 if (!actual.containsKey(e.key)) return false; 130 return actual.containsValue(e.value); 131 } 132 133 private String entryOrEntries(List<Entry> found) { 134 return found.size() == 1 ? ENTRY : ENTRIES; 135 } 136 137 /** 138 * Creates a new map entry. 139 * @param key the key of the entry. 140 * @param value the value of the entry. 141 * @return the created entry. 142 * @see #includes(org.fest.assertions.MapAssert.Entry...) 143 */ 144 public static Entry entry(Object key, Object value) { 145 return new Entry(key, value); 146 } 147 148 /** 149 * Understands an entry in a <code>{@link Map}</code>. 150 * 151 * @author Yvonne Wang 152 */ 153 public static class Entry { 154 final Object key; 155 final Object value; 156 157 Entry(Object key, Object value) { 158 this.key = key; 159 this.value = value; 160 } 161 162 /** @see java.lang.Object#toString() */ 163 @Override public String toString() { 164 return concat(quote(key), "=", quote(value)); 165 } 166 } 167 168 private void failIfNotFound(String description, Collection<?> notFound) { 169 failIfCustomMessageIsSet(); 170 fail(concat("the map:", formattedActual(), " does not contain the ", description, ":", inBrackets(notFound))); 171 } 172 173 private void validate(String description, Object[] objects) { 174 if (objects == null) 175 throw new NullPointerException( 176 formattedErrorMessage(concat("The given array of ", description, " should not be null"))); 177 } 178 179 private void failIfFound(String description, Collection<?> found) { 180 failIfCustomMessageIsSet(); 181 fail(concat("the map:", formattedActual(), " contains the ", description, ":", inBrackets(found))); 182 } 183 184 /** 185 * Verifies that the number of elements in the actual <code>{@link Map}</code> is equal to the given one. 186 * @param expected the expected number of elements in the actual <code>Map</code>. 187 * @return this assertion object. 188 * @throws AssertionError if the actual map is <code>null</code>. 189 * @throws AssertionError if the number of elements of the actual <code>Map</code> is not equal to the given one. 190 */ 191 public MapAssert hasSize(int expected) { 192 isNotNull(); 193 int actualSize = actualGroupSize(); 194 if (actualSize == expected) return this; 195 failIfCustomMessageIsSet(); 196 throw failure(concat( 197 "expected size:", inBrackets(expected)," but was:", inBrackets(actualSize), " for map:", inBrackets(actual))); 198 } 199 200 /** 201 * Verifies that the actual <code>{@link Map}</code> is <code>null</code> or empty. 202 * @throws AssertionError if the actual <code>Map</code> is not <code>null</code> or not empty. 203 */ 204 public final void isNullOrEmpty() { 205 if (Maps.isEmpty(actual)) return; 206 failIfCustomMessageIsSet(); 207 fail(concat("expecting a null or empty map, but was:", formattedActual())); 208 } 209 210 /** 211 * Verifies that the actual <code>{@link Map}</code> is empty. 212 * @throws AssertionError if the actual <code>Map</code> is <code>null</code> or not empty. 213 */ 214 public void isEmpty() { 215 isNotNull(); 216 if (actual.isEmpty()) return; 217 failIfCustomMessageIsSet(); 218 fail(concat("expecting empty map, but was:", formattedActual())); 219 } 220 221 private String formattedActual() { 222 return inBrackets(actual); 223 } 224 225 /** 226 * Verifies that the actual <code>{@link Map}</code> is equal to the given one. 227 * @param expected the given map to compare the actual <code>Map</code> to. 228 * @return this assertion object. 229 * @throws AssertionError if the actual <code>Map</code> is not equal to the given one. 230 */ 231 public MapAssert isEqualTo(Map<?, ?> expected) { 232 assertEqualTo(expected); 233 return this; 234 } 235 236 /** 237 * Verifies that the actual <code>{@link Map}</code> contains at least on element. 238 * @return this assertion object. 239 * @throws AssertionError if the actual <code>Map</code> is empty. 240 */ 241 public MapAssert isNotEmpty() { 242 isNotNull(); 243 if (!actual.isEmpty()) return this; 244 failIfCustomMessageIsSet(); 245 throw failure("expecting non-empty map, but it was empty"); 246 } 247 248 /** 249 * Verifies that the actual <code>{@link Map}</code> is not equal to the given one. 250 * @param other the given map to compare the actual <code>Map</code> to. 251 * @return this assertion object. 252 * @throws AssertionError if the actual <code>Map</code> is equal to the given one. 253 */ 254 public MapAssert isNotEqualTo(Map<?, ?> other) { 255 assertNotEqualTo(other); 256 return this; 257 } 258 259 /** 260 * Verifies that the actual <code>{@link Map}</code> is not <code>null</code>. 261 * @return this assertion object. 262 * @throws AssertionError if the actual <code>Map</code> is <code>null</code>. 263 */ 264 public MapAssert isNotNull() { 265 if (actual == null) fail("expecting a non-null map, but it was null"); 266 return this; 267 } 268 269 /** 270 * Verifies that the actual <code>{@link Map}</code> is not the same as the given one. 271 * @param other the given map to compare the actual <code>Map</code> to. 272 * @return this assertion object. 273 * @throws AssertionError if the actual <code>Map</code> is the same as the given one. 274 */ 275 public MapAssert isNotSameAs(Map<?, ?> other) { 276 assertNotSameAs(other); 277 return this; 278 } 279 280 /** 281 * Verifies that the actual <code>{@link Map}</code> is the same as the given one. 282 * @param expected the given map to compare the actual <code>Map</code> to. 283 * @return this assertion object. 284 * @throws AssertionError if the actual <code>Map</code> is not the same as the given one. 285 */ 286 public MapAssert isSameAs(Map<?, ?> expected) { 287 assertSameAs(expected); 288 return this; 289 } 290 291 /** 292 * Verifies that the actual <code>{@link Map}</code> satisfies the given condition. 293 * @param condition the given condition. 294 * @return this assertion object. 295 * @throws NullPointerException if the given condition is <code>null</code>. 296 * @throws AssertionError if the actual <code>Map</code> does not satisfy the given condition. 297 * @see #is(Condition) 298 */ 299 public MapAssert satisfies(Condition<Map<?, ?>> condition) { 300 assertSatisfies(condition); 301 return this; 302 } 303 304 /** 305 * Verifies that the actual <code>{@link Map}</code> does not satisfy the given condition. 306 * @param condition the given condition. 307 * @return this assertion object. 308 * @throws NullPointerException if the given condition is <code>null</code>. 309 * @throws AssertionError if the actual <code>Map</code> satisfies the given condition. 310 * @see #isNot(Condition) 311 */ 312 public MapAssert doesNotSatisfy(Condition<Map<?, ?>> condition) { 313 assertDoesNotSatisfy(condition); 314 return this; 315 } 316 317 /** 318 * Alias for <code>{@link #satisfies(Condition)}</code>. 319 * @param condition the given condition. 320 * @return this assertion object. 321 * @throws NullPointerException if the given condition is <code>null</code>. 322 * @throws AssertionError if the actual <code>Map</code> does not satisfy the given condition. 323 * @since 1.2 324 */ 325 public MapAssert is(Condition<Map<?, ?>> condition) { 326 assertIs(condition); 327 return this; 328 } 329 330 /** 331 * Alias for <code>{@link #doesNotSatisfy(Condition)}</code>. 332 * @param condition the given condition. 333 * @return this assertion object. 334 * @throws NullPointerException if the given condition is <code>null</code>. 335 * @throws AssertionError if the actual <code>Map</code> satisfies the given condition. 336 * @since 1.2 337 */ 338 public MapAssert isNot(Condition<Map<?, ?>> condition) { 339 assertIsNot(condition); 340 return this; 341 } 342 343 /** 344 * Returns the number of elements in the actual <code>{@link Map}</code>. 345 * @return the number of elements in the actual <code>{@link Map}</code>. 346 */ 347 protected int actualGroupSize() { 348 isNotNull(); 349 return actual.size(); 350 } 351 352 /** {@inheritDoc} */ 353 public MapAssert overridingErrorMessage(String message) { 354 replaceDefaultErrorMessagesWith(message); 355 return this; 356 } 357 }