@Test
  public void should_report_dodgy_field_if_cant_read_field_value() {
    DodgyBean person = new DodgyBean("Bill", "Kidd");

    expectedException.expect(IllegalArgumentException.class);
    expectedException.expectMessage(containsString("Could not find property value for firstName"));

    BeanMatcher firstNameIsBill = BeanMatchers.the("firstName", is("Bill"));
    BeanMatcher lastNameIsOddie = BeanMatchers.the("lastName", is("Oddie"));

    BeanMatcherAsserts.shouldMatch(person, firstNameIsBill, lastNameIsOddie);
  }
  @Test
  public void should_raise_issue_if_fields_cant_be_introspected() {
    DodgyBean person = new DodgyBean("Bill", "Kidd");

    expectedException.expect(IllegalArgumentException.class);
    expectedException.expectMessage(containsString("Could not read bean properties"));

    BeanMatcher lastNameIsOddie = BeanMatchers.the("lastName", is("Oddie"));

    BeanMatcherAsserts.shouldMatch(person, lastNameIsOddie);
  }
  @Test
  public void should_fail_test_if_field_does_not_exist() {
    DodgyBean person = new DodgyBean("Bill", "Oddie");

    expectedException.expect(IllegalArgumentException.class);
    expectedException.expectMessage(
        containsString("Could not find property value for field-does-not-exist"));

    BeanMatcher lastNameIsOddie = BeanMatchers.the("field-does-not-exist", is("Oddie"));

    BeanMatcherAsserts.shouldMatch(person, lastNameIsOddie);
  }
  @Test
  public void should_check_the_size_of_a_collection_and_its_contents() {
    List<Map<String, String>> persons =
        Arrays.asList(
            mappedPerson("Bill", "Oddie"),
            mappedPerson("Bill", "Kidd"),
            mappedPerson("Graeam", "Garden"),
            mappedPerson("Tim", "Brooke-Taylor"));

    BeanMatcher containsTwoEntries = BeanMatchers.the_count(is(2));
    BeanMatcher firstNameIsBill = BeanMatchers.the("firstName", is("Bill"));

    BeanMatcherAsserts.shouldMatch(persons, containsTwoEntries, firstNameIsBill);
  }
  @Test
  public void should_check_field_uniqueness() {
    List<Map<String, String>> persons =
        Arrays.asList(
            mappedPerson("Bill", "Oddie"),
            mappedPerson("Bill", "Kidd"),
            mappedPerson("Graeam", "Garden"),
            mappedPerson("Tim", "Brooke-Taylor"));

    BeanMatcher containsTwoEntries = BeanMatchers.the_count(is(2));
    BeanMatcher lastNamesAreDifferent = BeanMatchers.each("lastName").isDifferent();
    BeanMatcher firstNameIsBill = BeanMatchers.the("firstName", is("Bill"));

    BeanMatcherAsserts.shouldMatch(
        persons, containsTwoEntries, firstNameIsBill, lastNamesAreDifferent);
  }
  @Test
  public void should_display_detailed_diagnostics_when_a_single_bean_fails_to_match() {
    Person person = new Person("Bill", "Kidd");

    boolean assertionThrown = false;
    String exceptionMessage = null;
    try {
      BeanMatcher firstNameIsBill = BeanMatchers.the("firstName", is("Bill"));
      BeanMatcher lastNameIsOddie = BeanMatchers.the("lastName", is("Oddie"));

      BeanMatcherAsserts.shouldMatch(person, firstNameIsBill, lastNameIsOddie);
    } catch (AssertionError e) {
      assertionThrown = true;
      exceptionMessage = e.getMessage();
    }
    assertThat(assertionThrown, is(true));
    assertThat(
        exceptionMessage,
        allOf(
            containsString("Expected [firstName is 'Bill', lastName is 'Oddie'] but was"),
            containsString("firstName = 'Bill'"),
            containsString("lastName = 'Kidd")));
  }