@Valid 不会触发@Repository 中的验证
@Valid does not trigger validation in @Repository
我正在编写单元测试来检查输入验证是否在我的 Spring 存储库中起作用,但它看起来不像那样。
为简单起见,我有一个存储库 class:
@Repository
public class CustomerRepository {
// Java client for Redis, that I extend as JedisConnector in order to make it a Bean
private Jedis jedis;
@Autowired
public CustomerRepository(JedisConnector jedis) {
this.jedis = jedis;
}
private <S extends Customer> S save(@Valid S customer) throws CustomerException {
try {
this.jedis.set(...); // writing to Redis (mocked in test)
return customer;
} catch (JsonProcessingException e) {
throw new CustomerException(e.toString());
}
}
}
这使用以下模型class:
@AllArgsConstructor
@NoArgsConstructor
@Data // from Lombok
public class Customer {
@Email(message = "Email must be valid.")
private String identifier;
@NotBlank(message = "Password cannot be null or empty string.")
private String password;
@URL(message = "URL must be a url.")
private String url;
}
所以我写了一个这样的单元测试,期望它抛出一些我可以断言的异常:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {JedisConnector.class})
public class CustomerRepositoryTest {
// Cannot autowire because dependent bean needs to be configured
private CustomerRepository customerRepository;
@MockBean
JedisConnector jedisConnector;
@Before
public void setUp() {
// Configure Mock JedisConnector
MockitoAnnotations.initMocks(this);
Mockito.when(jedisConnector.select(anyInt())).thenReturn("OK");
// Manually wire dependency
customerRepository = new CustomerRepository(jedisConnector);
}
@Test
public void saveShouldFailOnInvalidInput() throws CustomerException {
Mockito.when(jedisConnector.set(anyString(), anyString())).thenReturn("OK");
// Blatantly invalid input
Customer customer = new Customer("testemail", "", "testurl");
customerRepository.save(customer);
}
}
但它只是运行,只输出调试消息(我在这个问题中遗漏了)。 如何执行验证?如果可能,我想避免在存储库的每个方法中显式调用验证器。
我在网上看到很多我试图重现的例子(从 Baeldung 到 DZone,当然这个网站上有很多问题,包括 this interesting one),但仍然没有成功。我错过了什么?
如果你想使用 repository
via 看起来你需要实现一个 integration test
以便通过显示 must not be blank
抛出 javax.validation.ConstraintViolationException
但如果你想测试只有那些验证,然后你将不得不通过以下方式使用验证器进行测试:
1.- 添加以下依赖项:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.13.Final</version>
</dependency>
2.- 为 Customer
字段添加自定义验证测试
import javax.validation.Validation;
import javax.validation.Validator;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
@RunWith(SpringRunner.class)
public class CustomerValidationTest {
private Validator validator;
@Before
public void setupValidatorInstance() {
validator = Validation.buildDefaultValidatorFactory().getValidator();
}
@Test
public void whenNotEmptyPassword_thenNoConstraintViolations() {
Customer customer = new Customer();
customer.setPassword("");
Set<ConstraintViolation<Customer>> violations = validator.validate(customer);
assertThat(violations.size()).isEqualTo(1);
}
}
我正在编写单元测试来检查输入验证是否在我的 Spring 存储库中起作用,但它看起来不像那样。
为简单起见,我有一个存储库 class:
@Repository
public class CustomerRepository {
// Java client for Redis, that I extend as JedisConnector in order to make it a Bean
private Jedis jedis;
@Autowired
public CustomerRepository(JedisConnector jedis) {
this.jedis = jedis;
}
private <S extends Customer> S save(@Valid S customer) throws CustomerException {
try {
this.jedis.set(...); // writing to Redis (mocked in test)
return customer;
} catch (JsonProcessingException e) {
throw new CustomerException(e.toString());
}
}
}
这使用以下模型class:
@AllArgsConstructor
@NoArgsConstructor
@Data // from Lombok
public class Customer {
@Email(message = "Email must be valid.")
private String identifier;
@NotBlank(message = "Password cannot be null or empty string.")
private String password;
@URL(message = "URL must be a url.")
private String url;
}
所以我写了一个这样的单元测试,期望它抛出一些我可以断言的异常:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {JedisConnector.class})
public class CustomerRepositoryTest {
// Cannot autowire because dependent bean needs to be configured
private CustomerRepository customerRepository;
@MockBean
JedisConnector jedisConnector;
@Before
public void setUp() {
// Configure Mock JedisConnector
MockitoAnnotations.initMocks(this);
Mockito.when(jedisConnector.select(anyInt())).thenReturn("OK");
// Manually wire dependency
customerRepository = new CustomerRepository(jedisConnector);
}
@Test
public void saveShouldFailOnInvalidInput() throws CustomerException {
Mockito.when(jedisConnector.set(anyString(), anyString())).thenReturn("OK");
// Blatantly invalid input
Customer customer = new Customer("testemail", "", "testurl");
customerRepository.save(customer);
}
}
但它只是运行,只输出调试消息(我在这个问题中遗漏了)。 如何执行验证?如果可能,我想避免在存储库的每个方法中显式调用验证器。
我在网上看到很多我试图重现的例子(从 Baeldung 到 DZone,当然这个网站上有很多问题,包括 this interesting one),但仍然没有成功。我错过了什么?
如果你想使用 repository
via 看起来你需要实现一个 integration test
以便通过显示 must not be blank
抛出 javax.validation.ConstraintViolationException
但如果你想测试只有那些验证,然后你将不得不通过以下方式使用验证器进行测试:
1.- 添加以下依赖项:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.13.Final</version>
</dependency>
2.- 为 Customer
字段添加自定义验证测试
import javax.validation.Validation;
import javax.validation.Validator;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
@RunWith(SpringRunner.class)
public class CustomerValidationTest {
private Validator validator;
@Before
public void setupValidatorInstance() {
validator = Validation.buildDefaultValidatorFactory().getValidator();
}
@Test
public void whenNotEmptyPassword_thenNoConstraintViolations() {
Customer customer = new Customer();
customer.setPassword("");
Set<ConstraintViolation<Customer>> violations = validator.validate(customer);
assertThat(violations.size()).isEqualTo(1);
}
}