"curry" runnables 的最干净方式
Cleanest way to "curry" runnables
我正在编写一个 JUnit 测试并希望 运行 测试一个对象有几个不同的变量。我通过传递 运行nables 来避免深层嵌套循环。
private Runnable withAges( final Person person, final Runnable r ) {
return () -> {
person.setAge( 0 );
r.run();
person.setAge( 50 );
r.run();
person.setAge( Integer.MAX_VALUE );
r.run();
person.setAge( -1 );
r.run();
person.setAge( Integer.MIN_VALUE );
r.run();
};
}
private Runnable withHair( final Person person, final Runnable r ) {
return () -> {
person.setHair( "blonde" );
r.run();
person.setHair( "BLONDE" );
r.run();
person.setHair( null );
r.run();
};
}
private Runnable withAddresses( final Person person, final Runnable r ) {
...
}
private Runnable withChildren( final Person person, final Runnable r ) {
...
}
实际测试为:
@Test
void testPerson() {
final Person person = new Person();
final Runnable tests = () -> {
assertTrue( ... );
assertFalse( ... );
}
...
}
目前,我可以运行这些测试使用
withAges( person,
withHair( person,
withAddresses( person,
withChildren( person, tests ) ) ) );
但是,如果我可以通过编写类似
的内容来清理它,那就太好了
withAges( person ).withHair( person ).withAddresses( person ).withChildren( person ).tests.run();
通过使 site
成为实例变量,我能够将其从 withX()
签名中删除。这让我可以通过
链接它们
withAges( withHair( withAddresses( withChildren( tests ) ) ) ).run()
不要误会:您当前和期望的方法都很难遵循。
据我所知,您正在尝试针对一组参数组合测试 Person
。
这显然是一种非惯用的方式。除此之外,您必须非常小心地恢复 Person
的可变状态,以免干扰测试。
您可能会发现像 JUnit Theories 这样的东西是一种更简单的方法:
@DataPoints("ages") Set<Integer> ages = Set.of(0, 50, Integer.MIN_VALUE, -1 /* etc */);
@DataPoints("hairs") Set<String> hairs = Set.of("blonde", "BLONDE" /* etc */);
/* etc */
@Theory
public void testSomething(
@FromDataPoints("ages") Integer age, @FromDataPoints("hairs") String hair) {
Person person = new Person();
person.setAge(age);
person.setHair(hair);
assertTrue(...);
assertFalse(...);
}
即使这样也会更容易理解(尽管它在同一个测试用例中测试多个东西,这有点令人不悦):
@Test
public void testSomething() {
for (int age : Set.of(...)) {
for (String hair : Set.of(...)) {
Person person = new Person();
person.setAge(age);
person.setHair(hair);
assertTrue(...);
assertFalse(...);
}
}
}
我正在编写一个 JUnit 测试并希望 运行 测试一个对象有几个不同的变量。我通过传递 运行nables 来避免深层嵌套循环。
private Runnable withAges( final Person person, final Runnable r ) {
return () -> {
person.setAge( 0 );
r.run();
person.setAge( 50 );
r.run();
person.setAge( Integer.MAX_VALUE );
r.run();
person.setAge( -1 );
r.run();
person.setAge( Integer.MIN_VALUE );
r.run();
};
}
private Runnable withHair( final Person person, final Runnable r ) {
return () -> {
person.setHair( "blonde" );
r.run();
person.setHair( "BLONDE" );
r.run();
person.setHair( null );
r.run();
};
}
private Runnable withAddresses( final Person person, final Runnable r ) {
...
}
private Runnable withChildren( final Person person, final Runnable r ) {
...
}
实际测试为:
@Test
void testPerson() {
final Person person = new Person();
final Runnable tests = () -> {
assertTrue( ... );
assertFalse( ... );
}
...
}
目前,我可以运行这些测试使用
withAges( person,
withHair( person,
withAddresses( person,
withChildren( person, tests ) ) ) );
但是,如果我可以通过编写类似
的内容来清理它,那就太好了withAges( person ).withHair( person ).withAddresses( person ).withChildren( person ).tests.run();
通过使 site
成为实例变量,我能够将其从 withX()
签名中删除。这让我可以通过
withAges( withHair( withAddresses( withChildren( tests ) ) ) ).run()
不要误会:您当前和期望的方法都很难遵循。
据我所知,您正在尝试针对一组参数组合测试 Person
。
这显然是一种非惯用的方式。除此之外,您必须非常小心地恢复 Person
的可变状态,以免干扰测试。
您可能会发现像 JUnit Theories 这样的东西是一种更简单的方法:
@DataPoints("ages") Set<Integer> ages = Set.of(0, 50, Integer.MIN_VALUE, -1 /* etc */);
@DataPoints("hairs") Set<String> hairs = Set.of("blonde", "BLONDE" /* etc */);
/* etc */
@Theory
public void testSomething(
@FromDataPoints("ages") Integer age, @FromDataPoints("hairs") String hair) {
Person person = new Person();
person.setAge(age);
person.setHair(hair);
assertTrue(...);
assertFalse(...);
}
即使这样也会更容易理解(尽管它在同一个测试用例中测试多个东西,这有点令人不悦):
@Test
public void testSomething() {
for (int age : Set.of(...)) {
for (String hair : Set.of(...)) {
Person person = new Person();
person.setAge(age);
person.setHair(hair);
assertTrue(...);
assertFalse(...);
}
}
}