@Test
  public void cascadingConstraintAtMethodReturnValue() throws Exception {

    BeanMetaData<CustomerRepository> metaData = setupBeanMetaData(CustomerRepository.class);

    Method method = CustomerRepository.class.getMethod("findCustomerByName", String.class);
    MethodMetaData methodMetaData = metaData.getMetaDataFor(method);

    assertEquals(methodMetaData.getParameterTypes(), method.getParameterTypes());
    assertTrue(methodMetaData.isCascading());
    assertIterableSize(methodMetaData, 0);
  }
  @Test
  public void nonCascadingConstraintAtMethodReturnValue() throws Exception {

    BeanMetaData<CustomerRepository> metaData = setupBeanMetaData(CustomerRepository.class);

    Method method = CustomerRepository.class.getMethod("baz");
    MethodMetaData methodMetaData = metaData.getMetaDataFor(method);

    assertEquals(methodMetaData.getParameterTypes(), method.getParameterTypes());
    assertFalse(methodMetaData.isCascading());
    ConstraintDescriptorImpl<? extends Annotation> descriptor =
        methodMetaData.iterator().next().getDescriptor();
    assertEquals(descriptor.getAnnotation().annotationType(), Min.class);
    assertEquals(descriptor.getAttributes().get("value"), 10L);
  }
  @Test(expectedExceptions = IllegalArgumentException.class)
  public void illegalParameterIndexCausesException() throws Exception {

    Method method = CustomerRepository.class.getMethod("foo");
    ExecutableMetaData methodMetaData =
        beanMetaData.getMetaDataFor(ExecutableElement.forMethod(method));

    methodMetaData.getParameterMetaData(0);
  }
  @Test
  public void locallyDefinedGroupConversion() throws Exception {

    Method method =
        CustomerRepository.class.getMethod("methodWithParameterGroupConversion", Set.class);
    ExecutableMetaData methodMetaData =
        beanMetaData.getMetaDataFor(ExecutableElement.forMethod(method));

    assertThat(methodMetaData.getParameterMetaData(0).convertGroup(Default.class))
        .isEqualTo(ValidationGroup.class);
  }
  @Test
  public void unconstrainedParameterMetaData() throws Exception {

    Method method = CustomerRepository.class.getMethod("updateCustomer", Customer.class);
    ExecutableMetaData methodMetaData =
        beanMetaData.getMetaDataFor(ExecutableElement.forMethod(method));

    ParameterMetaData parameterMetaData = methodMetaData.getParameterMetaData(0);

    assertFalse(parameterMetaData.isCascading());
    assertFalse(parameterMetaData.isConstrained());
    assertThat(parameterMetaData).isEmpty();
  }
  @Test
  public void cascadingParameterMetaData() throws Exception {

    Method method = CustomerRepository.class.getMethod("saveCustomer", Customer.class);
    ExecutableMetaData methodMetaData =
        beanMetaData.getMetaDataFor(ExecutableElement.forMethod(method));

    ParameterMetaData parameterMetaData = methodMetaData.getParameterMetaData(0);

    assertTrue(parameterMetaData.isCascading());
    assertTrue(parameterMetaData.isConstrained());
    assertEquals(parameterMetaData.getIndex(), 0);
    assertEquals(parameterMetaData.getName(), "arg0");
    assertThat(parameterMetaData).isEmpty();
  }
  @Test
  public void constrainedParameterMetaData() throws Exception {

    Method method =
        CustomerRepository.class.getMethod("createCustomer", CharSequence.class, String.class);
    ExecutableMetaData methodMetaData =
        beanMetaData.getMetaDataFor(ExecutableElement.forMethod(method));

    ParameterMetaData parameterMetaData = methodMetaData.getParameterMetaData(1);

    assertFalse(parameterMetaData.isCascading());
    assertTrue(parameterMetaData.isConstrained());
    assertEquals(parameterMetaData.getIndex(), 1);
    assertEquals(parameterMetaData.getName(), "arg1");
    assertThat(parameterMetaData).hasSize(1);
    assertEquals(
        parameterMetaData.iterator().next().getDescriptor().getAnnotation().annotationType(),
        NotNull.class);
  }