### Question:
FunctionalClass { public <F> @NonNull FunctionalProperty<T, F> field(final @NonNull String name) { final PropertyDescriptor descriptor = this.getPropertyDescriptor(name); return new FunctionalProperty<>(descriptor); }  FunctionalProperty<T, F> field(final @NonNull String name); Supplier<T> getConstructor();  }### Answer:
@Test void testGetSetterWithException() { @Data class PersonWithExceptionSetter { private String id; public void setId(final String id) { throw new UnsupportedOperationException("Foo"); } } final PersonWithExceptionSetter person = new PersonWithExceptionSetter(); final BiConsumer<PersonWithExceptionSetter, Object> setter = of(PersonWithExceptionSetter.class) .field("id").getSetter(); assertThatExceptionOfType(UnsupportedOperationException.class) .isThrownBy(() -> setter.accept(person, "foo")) .withMessage("Foo"); }
@Test void testGetGetter() { final Person person = new Person(); person.setId("foo"); final FunctionalProperty<Person, Object> id = of(Person.class).field("id"); final Function<Person, Object> getter = id.getGetter(); assertThat(getter.apply(person)) .isEqualTo("foo"); }
@Test void testGetGetterForMissingField() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> of(Person.class).field("i")) .withCauseInstanceOf(IntrospectionException.class) .withMessageContaining("Unknown property: i") .satisfies( exception -> assertThat(exception.getCause()).hasMessageContaining("Method not found: isI")); }
@Test void testGetGetterWithException() { @Data class PersonWithExceptionGetter { private String id; public String getId() { throw new UnsupportedOperationException("Foo"); } } final PersonWithExceptionGetter person = new PersonWithExceptionGetter(); person.setId("foo"); final FunctionalProperty<PersonWithExceptionGetter, Object> id = of(PersonWithExceptionGetter.class) .field("id"); final Function<PersonWithExceptionGetter, Object> getter = id.getGetter(); assertThatExceptionOfType(UnsupportedOperationException.class) .isThrownBy(() -> getter.apply(person)) .withMessage("Foo"); }
@Test void testGetMissingGetter() { class PersonWithoutGetter { @Setter private String id; } assertThatExceptionOfType(RuntimeException.class) .isThrownBy(() -> of(PersonWithoutGetter.class).field("id")) .withCauseInstanceOf(IntrospectionException.class) .withMessageContaining("Unknown property: id") .satisfies( exception -> assertThat(exception.getCause()).hasMessageContaining("Method not found: isId")); }
@Test void testGetMissingSetter() { class PersonWithoutSetter { @Getter private final String id = null; } assertThatExceptionOfType(RuntimeException.class) .isThrownBy(() -> of(PersonWithoutSetter.class).field("id")) .withCauseInstanceOf(IntrospectionException.class) .withMessageContaining("Unknown property: id") .satisfies( exception -> assertThat(exception.getCause()).hasMessageContaining("Method not found: setId")); }
@Test void testGetSetter() { final Person person = new Person(); final FunctionalProperty<Person, Object> id = of(Person.class).field("id"); final BiConsumer<Person, Object> setter = id.getSetter(); setter.accept(person, "foo"); assertThat(person.getId()) .isEqualTo("foo"); }
@Test void testGetSetterForMissingField() { assertThatExceptionOfType(RuntimeException.class) .isThrownBy(() -> of(Person.class).field("i")) .withCauseInstanceOf(IntrospectionException.class) .withMessageContaining("Unknown property: i") .satisfies( exception -> assertThat(exception.getCause()).hasMessageContaining("Method not found: isI")); }