测试Spring Boot @ConfigurationProperties验证失败

时间:2018-07-26 10:00:44

标签: spring-boot spring-boot-test

我想为@NotNull的{​​{1}},@NotEmpty验证编写测试。

@ConfigurationProperties

我的测试如下:

@Configuration
@ConfigurationProperties(prefix = "myPrefix", ignoreUnknownFields = true)
@Getter
@Setter
@Validated
public class MyServerConfiguration {
  @NotNull
  @NotEmpty
  private String baseUrl;
}

}

运行测试时,它报告运行测试之前启动应用程序失败:

@RunWith(SpringRunner.class)
@SpringBootTest()
public class NoActiveProfileTest {
  @Test(expected = org.springframework.boot.context.properties.bind.validation.BindValidationException.class)
  public void should_ThrowException_IfMandatoryPropertyIsMissing() throws Exception {
  }

我如何期望异常编写负面测试?即使我将*************************** APPLICATION FAILED TO START *************************** Description: Binding to target org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'myPrefix' to com.xxxxx.configuration.MyServerConfiguration$$EnhancerBySpringCGLIB$$4b91954c failed: 替换为BindException.class,应用程序也无法启动。

2 个答案:

答案 0 :(得分:0)

尝试以编程方式加载Spring Boot Application上下文:

简单版本

public class AppFailIT {

    @Test
    public void testFail() {
        try {
            new AnnotationConfigServletWebServerApplicationContext(MyApplication.class);
        }
        catch (Exception e){
            Assertions.assertThat(e).isInstanceOf(UnsatisfiedDependencyException.class);
            Assertions.assertThat(e.getMessage()).contains("nested exception is org.springframework.boot.context.properties.bind.BindException: Failed to bind properties");
            return;
        }
        fail();
    }
}

扩展版本 能够从application-test.properties加载环境并添加自己的key:values到方法级别的测试环境:

@TestPropertySource("classpath:application-test.properties")
public class AppFailIT {

    @Rule
    public final SpringMethodRule springMethodRule = new SpringMethodRule();

    @Autowired
    private ConfigurableEnvironment configurableEnvironment;

    @Test
    public void testFail() {
        try {
            MockEnvironment mockEnvironment = new MockEnvironment();
            mockEnvironment.withProperty("a","b");
            configurableEnvironment.merge(mockEnvironment);
            AnnotationConfigServletWebServerApplicationContext applicationContext = new AnnotationConfigServletWebServerApplicationContext();
            applicationContext.setEnvironment(configurableEnvironment);
            applicationContext.register(MyApplication.class);
            applicationContext.refresh();
        }
        catch (Exception e){
            Assertions.assertThat(e.getMessage()).contains("nested exception is org.springframework.boot.context.properties.bind.BindException: Failed to bind properties");
            return;
        }
        fail();
    }
}

答案 1 :(得分:0)

为此,我将使用ApplicationContextRunner

 new ApplicationContextRunner()
                .withConfiguration(AutoConfigurations.of(
                        ConfigurationPropertiesAutoConfiguration.class,
                        ValidationAutoConfiguration.class
                ))
                .withUserConfiguration(MyServerConfiguration.class)
                .withPropertyValues("foo=bar")
                .run(context -> {
                    var error = assertThrows(IllegalStateException.class, () -> context.getBean(MyServerConfiguration.class));

                    var validationError = (BindValidationException) ExceptionUtils.getRootCause(error);
                    var fieldViolation = (FieldError) validationError.getValidationErrors().iterator().next();
                    var fieldInError = fieldViolation.getObjectName() + "." + fieldViolation.getField();

                    assertThat(fieldInError, is(expectedFieldInError));
                    assertThat(fieldViolation.getDefaultMessage(), is(expectedMessage));
                });