@GwtIncompatible("java.lang.reflect.Field") public HasField hasField(final String fieldName) { final T subject = getSubject(); if (subject == null) { failureStrategy.fail("Cannot determine a field name from a null object."); // Needed for Expect and other non-terminal failure strategies return new HasField() { @Override public void withValue(Object value) { Subject.this.fail("Cannot test the presence of a value in a null object."); } }; } final Class<?> subjectClass = subject.getClass(); final Field field; try { field = ReflectionUtil.getField(subjectClass, fieldName); field.setAccessible(true); } catch (NoSuchFieldException e) { StringBuilder message = new StringBuilder("Not true that "); message.append("<").append(subjectClass.getSimpleName()).append(">"); message.append(" has a field named <").append(fieldName).append(">"); failureStrategy.fail(message.toString()); // Needed for Expect and other non-terminal failure strategies return new HasField() { @Override public void withValue(Object value) { Subject.this.fail("Cannot test the presence of a value in a non-present field."); } }; } return new HasField() { @Override public void withValue(Object expected) { try { Object actual = field.get(subject); if (expected == actual || (expected != null && expected.equals(actual))) { return; } else { StringBuilder message = new StringBuilder("Not true that "); message.append("<").append(subjectClass.getSimpleName()).append(">'s"); message.append(" field <").append(fieldName).append(">"); message.append(" contains expected value <").append(expected).append(">."); message.append(" It contains value <").append(actual).append(">"); failureStrategy.fail(message.toString()); } } catch (IllegalArgumentException e) { throw new RuntimeException( "Error checking field " + fieldName + " while testing for value " + expected); } catch (IllegalAccessException e) { throw new RuntimeException( "Cannot access field " + fieldName + " to test for value " + expected); } } }; }
/** * Assembles a failure message with an alternative representation of the wrapped subject and * passes it to the FailureStrategy * * @param verb the proposition being asserted * @param expected the expected value of the proposition * @param actual the custom representation of the subject to be reported in the failure. */ protected void failWithCustomSubject(String verb, Object expected, Object actual) { String message = format( "Not true that <%s> %s <%s>", ((actual == null) ? "null reference" : actual), verb, expected); failureStrategy.fail(message); }
/** * Assembles a failure message and passes such to the FailureStrategy * * @param verb the proposition being asserted * @param messageParts the expectations against which the subject is compared */ protected void fail(String verb, Object... messageParts) { StringBuilder message = new StringBuilder("Not true that "); message.append(getDisplaySubject()).append(" ").append(verb); for (Object part : messageParts) { message.append(" <").append(part).append(">"); } failureStrategy.fail(message.toString()); }
/** * Assembles a failure message and passes it to the FailureStrategy * * @param verb the proposition being asserted * @param messageParts the expectations against which the subject is compared */ protected void failWithBadResults(String verb, Object expected, String failVerb, Object actual) { String message = format( "Not true that %s %s <%s>. It %s <%s>", getDisplaySubject(), verb, expected, failVerb, ((actual == null) ? "null reference" : actual)); failureStrategy.fail(message); }
/** * Passes through a failure message verbatim. Used for {@link Subject} subclasses which need to * provide alternate language for more fit-to-purpose error messages. * * @param message the message template to be passed to the failure. Note, this method only * guarantees to process {@code %s} tokens. It is not guaranteed to be compatible with {@code * String.format()}. Any other formatting desired (such as floats or scientific notation) * should be performed before the method call and the formatted value passed in as a string. * @param paramters the object parameters which will be applied to the message template. */ protected void failWithRawMessage(String message, Object... parameters) { failureStrategy.fail(format(message, parameters)); }
/** * Assembles a failure message without a given subject and passes it to the FailureStrategy * * @param verb the proposition being asserted */ protected void failWithoutSubject(String verb) { String subject = this.customName == null ? "the subject" : "\"" + customName + "\""; failureStrategy.fail(format("Not true that %s %s", subject, verb)); }