package net.thucydides.core.matchers;
import org.hamcrest.Matcher;
import org.joda.time.DateTime;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import java.math.BigDecimal;
import static net.thucydides.core.matchers.dates.DateMatchers.isAfter;
import static org.fest.assertions.Assertions.assertThat;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
public class WhenMatchingPropertyValues {
public class Person {
private final String firstName;
private final String lastName;
private final DateTime birthday;
private final BigDecimal favoriteNumber;
Person(String firstName, String lastName, DateTime birthday) {
this(firstName, lastName, birthday, new BigDecimal("0.0"));
}
Person(String firstName, String lastName, DateTime birthday, BigDecimal favoriteNumber) {
this.firstName = firstName;
this.lastName = lastName;
this.birthday = birthday;
this.favoriteNumber = favoriteNumber;
}
Person(String firstName, String lastName) {
this(firstName, lastName, new DateTime(), new BigDecimal("0.0"));
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public DateTime getBirthday() {
return birthday;
}
public BigDecimal getFavoriteNumber() {
return favoriteNumber;
}
}
@Test
public void should_match_field_by_name() {
BeanFieldMatcher matcher = new BeanPropertyMatcher("firstName", is("Bill"));
Person person = new Person("Bill", "Oddie");
assertThat(matcher.matches(person)).isTrue();
}
@Test
public void should_match_date_fields() {
Person bill = new Person("Bill", "Oddie", new DateTime(1950, 1, 1, 12, 1));
BeanFieldMatcher birthdayAfter1900 = new BeanPropertyMatcher("birthday", isAfter(new DateTime(1900, 1, 1, 1, 0)));
assertThat(birthdayAfter1900.matches(bill)).isTrue();
}
@Test
public void should_match_number_fields() {
Person bill = new Person("Bill", "Oddie", new DateTime(1950, 1, 1, 12, 1), new BigDecimal("42.1"));
BeanFieldMatcher favoriteNumberIsNot42 = new BeanPropertyMatcher("favoriteNumber", greaterThan(new BigDecimal("42")));
assertThat(favoriteNumberIsNot42.matches(bill)).isTrue();
}
@Test
public void should_fail_if_match_is_not_successful() {
BeanFieldMatcher matcher = new BeanPropertyMatcher("firstName", is("Bill"));
Person person = new Person("Graeam", "Garden");
assertThat(matcher.matches(person)).isFalse();
}
@Test
public void should_display_expected_values_when_printed() {
BeanMatcher matcher = new BeanPropertyMatcher("firstName", is("Bill"));
assertThat(matcher.toString()).isEqualTo("firstName is 'Bill'");
}
@Test
public void should_obtain_matcher_from_fluent_static_method() {
BeanFieldMatcher matcher = (BeanFieldMatcher) BeanMatchers.the("firstName", is("Bill"));
Person person = new Person("Bill", "Oddie");
assertThat(matcher.matches(person)).isTrue();
}
@Test
public void should_obtain_instanciated_matcher_from_matcher() {
Matcher<Object> matcher = ((BeanFieldMatcher) BeanMatchers.the("firstName", is("Bill"))).getMatcher();
Person person = new Person("Bill", "Oddie");
assertThat(matcher.matches(person)).isTrue();
}
@Test
public void instanciated_matcher_should_provide_meaningful_description() {
Matcher<Object> matcher = ((BeanFieldMatcher)BeanMatchers.the("firstName", is("Bill"))).getMatcher();
assertThat(matcher.toString()).isEqualTo("firstName is 'Bill'");
}
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Test
public void should_match_against_a_single_bean() {
Person person = new Person("Bill", "Oddie");
BeanMatcher firstNameIsBill = BeanMatchers.the("firstName", is("Bill"));
BeanMatcher lastNameIsOddie = BeanMatchers.the("lastName", is("Oddie"));
assertThat(BeanMatcherAsserts.matches(person, firstNameIsBill, lastNameIsOddie)).isTrue();
}
@Test
public void should_not_match_against_non_matching_single_bean() {
Person person = new Person("Bill", "Kidd");
BeanMatcher firstNameIsBill = BeanMatchers.the("firstName", is("Bill"));
BeanMatcher lastNameIsOddie = BeanMatchers.the("lastName", is("Oddie"));
assertThat(BeanMatcherAsserts.matches(person, firstNameIsBill, lastNameIsOddie)).isFalse();
}
@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")));
}
@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);
}
public class DodgyBean {
private final String firstName;
private final String lastName;
DodgyBean(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
throw new IllegalAccessError();
}
public String getLastName() {
return lastName;
}
}
@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);
}
}