我想编写单元测试,它验证了bean验证约束的正确配置。我认为应该对数据集进行测试,因此它会验证许多不同的组合。
到目前为止,我制作了这段代码:
@RunWith(Parameterized.class)
public class TagTest {
private Validator validator;
@Parameterized.Parameter
public Pair<Boolean, Tag> tagPair;
@Parameterized.Parameters
public static Collection<Pair<Boolean, Tag>> testData() {
Collection<Pair<Boolean, Tag>> tags = new ArrayList<>();
Tag tag = new Tag();
tag.setId(1L);
tag.setVersion(1L);
tag.setTitle("Sample");
tags.add(new ImmutablePair<>(true, tag));
// ... more sample data
return tags;
}
@Before
public void init() {
ValidatorFactory vf = Validation.buildDefaultValidatorFactory();
this.validator = vf.getValidator();
}
@Test
public void shouldBeValidated() {
Set<ConstraintViolation<Tag>> violations = validator.validate(
tagPair.getRight());
Assert.assertTrue(violations.isEmpty() == tagPair.getLeft());
}
}
从中读取样本数据的最佳解决方案是什么?在代码中保存数据对我来说并不合适。我的例子中的标签是扁平物体。如果对象会很复杂怎么办?
单元测试是否可以接受,我会对bean验证进行一般测试,这将接受Object
(在我的情况下代替Tag
),然后验证我将推送的任何数据?
答案 0 :(得分:0)
尽量保持简单。例如。尽量使测试数据接近测试逻辑。有两种或多或少的好方法可以实现您的需求:
@DataProvider
你也可以转向像Spock这样提供最好的数据提供者的其他框架,但它们通常用动态语言(如Groovy)编写,这会带来更多弊大于利。
另一种选择当然是使用@RunWith(Parameterized.class)
。但这是一个非常奇怪的机制,我没有看到有人在现实生活中使用它,因为它有多么不方便。您还可以查看@Theory
。
这是JUnit的真实例子:
@Test public void validationMustPass_forValidExperimentName() {
assertExperimentNameValidationPasses("Min boundary", alphanumeric(1));
assertExperimentNameValidationPasses("Max boundary", alphanumeric(20));
assertExperimentNameValidationPasses("With all alphanumerics and allowed special characters",
between(2, 19).with(multipleOf("_-")).alphanumeric());
assertExperimentNameValidationPasses("With spaces", between(2, 19).with(oneOf(" ")).alphanumeric());
assertExperimentNameValidationPasses("Only numbers", between(2, 19).numeric());
assertExperimentNameValidationPasses("Only dashes", between(2, 19).string('-'));
assertExperimentNameValidationPasses("Only underscores", between(2, 19).string('_'));
}
@Test public void mustNotCreateExperimentWithWrongExperimentName() {
assertExperimentNameValidationFails(
"Longer than max allowed length",
"Should be between 1 and 20 symbols.",
length(21).alphanumeric());
assertExperimentNameValidationFails("Experiment name is white space",
"Should be between 1 and 20 symbols.",
" ");
assertExperimentNameValidationFails("Experiment name is empty",
"Should be between 1 and 20 symbols.",
"");
assertExperimentNameValidationFails("Experiment name contains not allowed symbols",
"Only English letters, numbers, spaces, dashes and underscores are allowed",
length(10).with(oneOf(FORBIDDEN_CHARACTERS)).alphanumeric());
}
这仅仅是对象的1个字段。这是doing this with Spock的一个例子,但正如我所提到的 - 它通常是不值得的。以下是keep data management effective的一些基本规则。