参数化测试因 mvn 测试而失败
Parameterized tests fail with mvn test
我在一个简单的参数化 java 测试中苦苦挣扎,找不到合适的解决方案:-S
也许你可以给我一个提示,我错过了什么。
以下场景我一直在测试
运行
- intellij -> 没有错误,所有测试通过
mvn clean -Dtest:KnockoutTests test
-> 没有错误,所有测试通过
mvn clean test
(在本地和在 jenkins 上)-> ArrayIndexOutOfBoundsException
当我在 class RoundDefinition
中复制完全生成的 hashCode
方法时,它工作得很好。但是我不想用生成的方法明确地覆盖 hashCode
方法...(这显然不是解决方案)
型号
@Entity
@Data
@Table( name = "tbl_rounddefinition" )
@JsonIgnoreProperties( value = { "hibernateLazyInitializer", "handler", }, ignoreUnknown = true )
@ToString( exclude = { "tournament" } )
@EqualsAndHashCode( exclude = { "tournament" } )
public class RoundDefinition implements Serializable {
@Id
@GeneratedValue( strategy = IDENTITY )
@Column( name = "rounddefinition_id" )
private Long id;
@ManyToOne( fetch = FetchType.LAZY )
@JoinColumn( name = "rounddefinition_linktournamentid" )
@JsonIdentityInfo( generator = ObjectIdGenerators.PropertyGenerator.class, property = "id" )
@JsonIdentityReference( alwaysAsId = true )
private Tournament tournament;
@Column( name = "rounddefinition_round" )
private Integer round;
@Column( name = "rounddefinition_numberOfRoundresults" )
private Integer numberOfRoundresults;
}
@Data
@ToString( exclude = { [...] } )
@EqualsAndHashCode( exclude = { [...], "roundDefinitions" } )
@Entity
@Table( name = "tbl_tournament" )
@JsonIgnoreProperties( value = { "hibernateLazyInitializer", "handler" }, ignoreUnknown = true )
public class Tournament implements Serializable {
[...]
@OneToMany( fetch = FetchType.LAZY, mappedBy = "tournament", cascade = CascadeType.ALL, orphanRemoval = true )
@JsonSerialize( using = CollectionSerializer.class )
@JsonDeserialize( using = CollectionDeserializer.class )
@OrderBy( " round ASC " )
private Set<RoundDefinition> roundDefinitions = new HashSet<>();
[...]
}
测试
@RunWith( Parameterized.class )
@Slf4j
public class KnockoutTests {
@InjectMocks
private Knockout underTest;
@Mock
private MatchRepository matchRepository;
private Integer tournamentSize;
private Integer expectedMatchSize;
private Integer expectedMaxRound;
private List<RoundDefinition> roundDefinitions;
public KnockoutTests( Integer tournamentSize, Integer expectedMatchSize, Integer expectedMaxRound,
List<RoundDefinition> roundDefinitions )
{
this.tournamentSize = tournamentSize;
this.expectedMatchSize = expectedMatchSize;
this.expectedMaxRound = expectedMaxRound;
this.roundDefinitions = roundDefinitions;
}
@Before
public void setUp() {
MockitoAnnotations.initMocks( this );
}
@Test
public void testGenerate() {
Tournament tournament = new Tournament();
tournament.setTeamsize( 1 );
System.out.println( "############# " + roundDefinitions.toString() + " #############" );
tournament.setRoundDefinitions( new HashSet<>( roundDefinitions ) ); // <<-- Here I'm getting this weird ArrayIndexOutOfBoundsExceptions
[...]
}
@Parameterized.Parameters( name = "{index}: Test with tournamentSize={0}, expectedMatchSize: {1}, expectedMaxRound: {2}" )
public static Collection testData() {
return Arrays.asList( new Object[][] {
{ 1, 1, 1, new ArrayList<RoundDefinition>() {{
add( getRoundDefinition( 1L, 1, 1 ) );
}} },
{ 2, 1, 1, new ArrayList<RoundDefinition>() {{
add( getRoundDefinition( 1L, 1, 1 ) );
}} },
{ 15, 15, 4, new ArrayList<RoundDefinition>() {{
add( getRoundDefinition( 1L, 1, 1 ) );
add( getRoundDefinition( 2L, 3, 3 ) );
add( getRoundDefinition( 3L, 4, 5 ) );
}} },
{ 16, 15, 4, new ArrayList<RoundDefinition>() {{
add( getRoundDefinition( 1L, 1, 1 ) );
}} },
{ 17, 31, 5, new ArrayList<RoundDefinition>() {{
add( getRoundDefinition( 1L, 1, 1 ) );
}} },
{ 129, 255, 8, new ArrayList<RoundDefinition>() {{
add( getRoundDefinition( 1L, 1, 1 ) );
}} },
{ 256, 255, 8, new ArrayList<RoundDefinition>() {{
add( getRoundDefinition( 1L, 1, 1 ) );
}} },
{ 257, 511, 9, new ArrayList<RoundDefinition>() {{
add( getRoundDefinition( 1L, 1, 1 ) );
add( getRoundDefinition( 2L, 3, 3 ) );
add( getRoundDefinition( 3L, 4, 5 ) );
}} }
} );
}
private static RoundDefinition getRoundDefinition( long id, int round, int numberOfRoundresults ) {
RoundDefinition rd = new RoundDefinition();
rd.setId( id );
rd.setRound( round );
rd.setNumberOfRoundresults( numberOfRoundresults );
return rd;
}
[...]
}
控制台输出
############# [RoundDefinition(id=1, tournament=null, round=1, numberOfRoundresults=1)] #############
############# [RoundDefinition(id=1, tournament=null, round=1, numberOfRoundresults=1), RoundDefinition(id=2, tournament=null, round=3, numberOfRoundresults=3), RoundDefinition(id=3, tournament=null, round=4, numberOfRoundresults=5)] #############
############# [RoundDefinition(id=1, tournament=null, round=1, numberOfRoundresults=1)] #############
############# [RoundDefinition(id=1, tournament=null, round=1, numberOfRoundresults=1)] #############
############# [RoundDefinition(id=1, tournament=null, round=1, numberOfRoundresults=1)] #############
############# [RoundDefinition(id=1, tournament=null, round=1, numberOfRoundresults=1)] #############
############# [RoundDefinition(id=1, tournament=null, round=1, numberOfRoundresults=1), RoundDefinition(id=2, tournament=null, round=3, numberOfRoundresults=3), RoundDefinition(id=3, tournament=null, round=4, numberOfRoundresults=5)] #############
Tests run: 8, Failures: 0, Errors: 8, Skipped: 0, Time elapsed: 0.015 sec <<< FAILURE! - in pkg.service.tournament.handler.generator.KnockoutTests
testGenerate[0: Test with tournamentSize=1, expectedMatchSize: 1, expectedMaxRound: 1](pkg.service.tournament.handler.generator.KnockoutTests) Time elapsed: 0.008 sec <<< ERROR!
java.lang.ArrayIndexOutOfBoundsException: 35
at pkg.model.entities.RoundDefinition.hashCode(RoundDefinition.java:26)
at java.util.HashMap.hash(HashMap.java:339)
at java.util.HashMap.put(HashMap.java:612)
at java.util.HashSet.add(HashSet.java:220)
at java.util.AbstractCollection.addAll(AbstractCollection.java:344)
at java.util.HashSet.<init>(HashSet.java:120)
at pkg.service.tournament.handler.generator.KnockoutTests.testGenerate(KnockoutTests.java:67)
testGenerate[1: Test with tournamentSize=2, expectedMatchSize: 1, expectedMaxRound: 1](pkg.service.tournament.handler.generator.KnockoutTests) Time elapsed: 0 sec <<< ERROR!
java.lang.ArrayIndexOutOfBoundsException: 35
at pkg.model.entities.RoundDefinition.hashCode(RoundDefinition.java:26)
at java.util.HashMap.hash(HashMap.java:339)
at java.util.HashMap.put(HashMap.java:612)
at java.util.HashSet.add(HashSet.java:220)
at java.util.AbstractCollection.addAll(AbstractCollection.java:344)
at java.util.HashSet.<init>(HashSet.java:120)
at pkg.service.tournament.handler.generator.KnockoutTests.testGenerate(KnockoutTests.java:67)
lombok 生成的代码
public int hashCode() {
int PRIME = true;
int result = 1;
Object $id = this.getId();
int result = result * 59 + ($id == null ? 43 : $id.hashCode());
Object $round = this.getRound();
result = result * 59 + ($round == null ? 43 : $round.hashCode());
Object $numberOfRoundresults = this.getNumberOfRoundresults();
result = result * 59 + ($numberOfRoundresults == null ? 43 : $numberOfRoundresults.hashCode());
return result;
}
#2 编辑:
切换到显式生成
Set<RoundDefinition> definitions = new HashSet<>( );
for (RoundDefinition rd : roundDefinitions) {
RoundDefinition asd = new RoundDefinition();
asd.setRound( rd.getRound() );
asd.setNumberOfRoundresults( rd.getNumberOfRoundresults() );
definitions.add(asd); // <-- ArrayIndexOutOfBoundsException
}
#3 编辑:
出于好奇,我尝试将一个元素添加到另一组 class
Set<Tournament> tournamentSet = new HashSet<>();
tournamentSet.add(new Tournament()); <-- ArrayIndexOutOfBoundsException
还将这样的初始化添加到其他测试中...相同的行为o.O
但是我可以将字符串添加到 HashSet<String>
... 这到底是怎么回事 :-D
#4 编辑:
已检查更改的依赖项,但它们似乎与源代码分支相同。也可在源代码分支中重现...
#5 编辑:
从我的模型 "RoundDefinition" 中删除了 lombok 注释“@Data”,我自己写了 getter 和 setter 并且测试再次正常工作......
使用龙目岛 v1.18.8
那么为什么lombok生成hashCode和equals函数时会失败....
太棒了,我终于到了可以继续的地步了...
当我测试了几次尝试时,我注意到我的测试以某种方式再次起作用。
当我 运行 带有配置文件的测试失败时,当 运行 没有配置文件时它们工作。
经过一些挖掘和重构后,我得到了项目的 pom 文件...
插件"maven-sufefire-plugin"被添加了2次这样
<project>
<profiles>
[...]
<profile>
<id>unit-test</id>
<plugins>
[...]
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>
${argLine} -Dfile.encodeing=utf-8 -Duser.timezone=UTC
</argLine>
</configuration>
</plugin>
[...]
<project>
<build>
<plugins>
[...]
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>
-Dfile.encodeing=utf-8 -Duser.timezone=UTC
</argLine>
</configuration>
</plugin>
[...]
但是 属性 ${argLine}
根本没有在 pom 文件中设置。
所以我引入了一个新的 属性 <argLine>
并将这些参数放在那里……瞧,它起作用了……
不知道为什么 hashcode 方法会抛出异常,但也许这对其他人也有帮助:-)
我在一个简单的参数化 java 测试中苦苦挣扎,找不到合适的解决方案:-S
也许你可以给我一个提示,我错过了什么。
以下场景我一直在测试 运行
- intellij -> 没有错误,所有测试通过
mvn clean -Dtest:KnockoutTests test
-> 没有错误,所有测试通过mvn clean test
(在本地和在 jenkins 上)-> ArrayIndexOutOfBoundsException
当我在 class RoundDefinition
中复制完全生成的 hashCode
方法时,它工作得很好。但是我不想用生成的方法明确地覆盖 hashCode
方法...(这显然不是解决方案)
型号
@Entity
@Data
@Table( name = "tbl_rounddefinition" )
@JsonIgnoreProperties( value = { "hibernateLazyInitializer", "handler", }, ignoreUnknown = true )
@ToString( exclude = { "tournament" } )
@EqualsAndHashCode( exclude = { "tournament" } )
public class RoundDefinition implements Serializable {
@Id
@GeneratedValue( strategy = IDENTITY )
@Column( name = "rounddefinition_id" )
private Long id;
@ManyToOne( fetch = FetchType.LAZY )
@JoinColumn( name = "rounddefinition_linktournamentid" )
@JsonIdentityInfo( generator = ObjectIdGenerators.PropertyGenerator.class, property = "id" )
@JsonIdentityReference( alwaysAsId = true )
private Tournament tournament;
@Column( name = "rounddefinition_round" )
private Integer round;
@Column( name = "rounddefinition_numberOfRoundresults" )
private Integer numberOfRoundresults;
}
@Data
@ToString( exclude = { [...] } )
@EqualsAndHashCode( exclude = { [...], "roundDefinitions" } )
@Entity
@Table( name = "tbl_tournament" )
@JsonIgnoreProperties( value = { "hibernateLazyInitializer", "handler" }, ignoreUnknown = true )
public class Tournament implements Serializable {
[...]
@OneToMany( fetch = FetchType.LAZY, mappedBy = "tournament", cascade = CascadeType.ALL, orphanRemoval = true )
@JsonSerialize( using = CollectionSerializer.class )
@JsonDeserialize( using = CollectionDeserializer.class )
@OrderBy( " round ASC " )
private Set<RoundDefinition> roundDefinitions = new HashSet<>();
[...]
}
测试
@RunWith( Parameterized.class )
@Slf4j
public class KnockoutTests {
@InjectMocks
private Knockout underTest;
@Mock
private MatchRepository matchRepository;
private Integer tournamentSize;
private Integer expectedMatchSize;
private Integer expectedMaxRound;
private List<RoundDefinition> roundDefinitions;
public KnockoutTests( Integer tournamentSize, Integer expectedMatchSize, Integer expectedMaxRound,
List<RoundDefinition> roundDefinitions )
{
this.tournamentSize = tournamentSize;
this.expectedMatchSize = expectedMatchSize;
this.expectedMaxRound = expectedMaxRound;
this.roundDefinitions = roundDefinitions;
}
@Before
public void setUp() {
MockitoAnnotations.initMocks( this );
}
@Test
public void testGenerate() {
Tournament tournament = new Tournament();
tournament.setTeamsize( 1 );
System.out.println( "############# " + roundDefinitions.toString() + " #############" );
tournament.setRoundDefinitions( new HashSet<>( roundDefinitions ) ); // <<-- Here I'm getting this weird ArrayIndexOutOfBoundsExceptions
[...]
}
@Parameterized.Parameters( name = "{index}: Test with tournamentSize={0}, expectedMatchSize: {1}, expectedMaxRound: {2}" )
public static Collection testData() {
return Arrays.asList( new Object[][] {
{ 1, 1, 1, new ArrayList<RoundDefinition>() {{
add( getRoundDefinition( 1L, 1, 1 ) );
}} },
{ 2, 1, 1, new ArrayList<RoundDefinition>() {{
add( getRoundDefinition( 1L, 1, 1 ) );
}} },
{ 15, 15, 4, new ArrayList<RoundDefinition>() {{
add( getRoundDefinition( 1L, 1, 1 ) );
add( getRoundDefinition( 2L, 3, 3 ) );
add( getRoundDefinition( 3L, 4, 5 ) );
}} },
{ 16, 15, 4, new ArrayList<RoundDefinition>() {{
add( getRoundDefinition( 1L, 1, 1 ) );
}} },
{ 17, 31, 5, new ArrayList<RoundDefinition>() {{
add( getRoundDefinition( 1L, 1, 1 ) );
}} },
{ 129, 255, 8, new ArrayList<RoundDefinition>() {{
add( getRoundDefinition( 1L, 1, 1 ) );
}} },
{ 256, 255, 8, new ArrayList<RoundDefinition>() {{
add( getRoundDefinition( 1L, 1, 1 ) );
}} },
{ 257, 511, 9, new ArrayList<RoundDefinition>() {{
add( getRoundDefinition( 1L, 1, 1 ) );
add( getRoundDefinition( 2L, 3, 3 ) );
add( getRoundDefinition( 3L, 4, 5 ) );
}} }
} );
}
private static RoundDefinition getRoundDefinition( long id, int round, int numberOfRoundresults ) {
RoundDefinition rd = new RoundDefinition();
rd.setId( id );
rd.setRound( round );
rd.setNumberOfRoundresults( numberOfRoundresults );
return rd;
}
[...]
}
控制台输出
############# [RoundDefinition(id=1, tournament=null, round=1, numberOfRoundresults=1)] #############
############# [RoundDefinition(id=1, tournament=null, round=1, numberOfRoundresults=1), RoundDefinition(id=2, tournament=null, round=3, numberOfRoundresults=3), RoundDefinition(id=3, tournament=null, round=4, numberOfRoundresults=5)] #############
############# [RoundDefinition(id=1, tournament=null, round=1, numberOfRoundresults=1)] #############
############# [RoundDefinition(id=1, tournament=null, round=1, numberOfRoundresults=1)] #############
############# [RoundDefinition(id=1, tournament=null, round=1, numberOfRoundresults=1)] #############
############# [RoundDefinition(id=1, tournament=null, round=1, numberOfRoundresults=1)] #############
############# [RoundDefinition(id=1, tournament=null, round=1, numberOfRoundresults=1), RoundDefinition(id=2, tournament=null, round=3, numberOfRoundresults=3), RoundDefinition(id=3, tournament=null, round=4, numberOfRoundresults=5)] #############
Tests run: 8, Failures: 0, Errors: 8, Skipped: 0, Time elapsed: 0.015 sec <<< FAILURE! - in pkg.service.tournament.handler.generator.KnockoutTests
testGenerate[0: Test with tournamentSize=1, expectedMatchSize: 1, expectedMaxRound: 1](pkg.service.tournament.handler.generator.KnockoutTests) Time elapsed: 0.008 sec <<< ERROR!
java.lang.ArrayIndexOutOfBoundsException: 35
at pkg.model.entities.RoundDefinition.hashCode(RoundDefinition.java:26)
at java.util.HashMap.hash(HashMap.java:339)
at java.util.HashMap.put(HashMap.java:612)
at java.util.HashSet.add(HashSet.java:220)
at java.util.AbstractCollection.addAll(AbstractCollection.java:344)
at java.util.HashSet.<init>(HashSet.java:120)
at pkg.service.tournament.handler.generator.KnockoutTests.testGenerate(KnockoutTests.java:67)
testGenerate[1: Test with tournamentSize=2, expectedMatchSize: 1, expectedMaxRound: 1](pkg.service.tournament.handler.generator.KnockoutTests) Time elapsed: 0 sec <<< ERROR!
java.lang.ArrayIndexOutOfBoundsException: 35
at pkg.model.entities.RoundDefinition.hashCode(RoundDefinition.java:26)
at java.util.HashMap.hash(HashMap.java:339)
at java.util.HashMap.put(HashMap.java:612)
at java.util.HashSet.add(HashSet.java:220)
at java.util.AbstractCollection.addAll(AbstractCollection.java:344)
at java.util.HashSet.<init>(HashSet.java:120)
at pkg.service.tournament.handler.generator.KnockoutTests.testGenerate(KnockoutTests.java:67)
lombok 生成的代码
public int hashCode() {
int PRIME = true;
int result = 1;
Object $id = this.getId();
int result = result * 59 + ($id == null ? 43 : $id.hashCode());
Object $round = this.getRound();
result = result * 59 + ($round == null ? 43 : $round.hashCode());
Object $numberOfRoundresults = this.getNumberOfRoundresults();
result = result * 59 + ($numberOfRoundresults == null ? 43 : $numberOfRoundresults.hashCode());
return result;
}
#2 编辑:
切换到显式生成
Set<RoundDefinition> definitions = new HashSet<>( );
for (RoundDefinition rd : roundDefinitions) {
RoundDefinition asd = new RoundDefinition();
asd.setRound( rd.getRound() );
asd.setNumberOfRoundresults( rd.getNumberOfRoundresults() );
definitions.add(asd); // <-- ArrayIndexOutOfBoundsException
}
#3 编辑:
出于好奇,我尝试将一个元素添加到另一组 class
Set<Tournament> tournamentSet = new HashSet<>();
tournamentSet.add(new Tournament()); <-- ArrayIndexOutOfBoundsException
还将这样的初始化添加到其他测试中...相同的行为o.O
但是我可以将字符串添加到 HashSet<String>
... 这到底是怎么回事 :-D
#4 编辑:
已检查更改的依赖项,但它们似乎与源代码分支相同。也可在源代码分支中重现...
#5 编辑:
从我的模型 "RoundDefinition" 中删除了 lombok 注释“@Data”,我自己写了 getter 和 setter 并且测试再次正常工作...... 使用龙目岛 v1.18.8
那么为什么lombok生成hashCode和equals函数时会失败....
太棒了,我终于到了可以继续的地步了...
当我测试了几次尝试时,我注意到我的测试以某种方式再次起作用。
当我 运行 带有配置文件的测试失败时,当 运行 没有配置文件时它们工作。 经过一些挖掘和重构后,我得到了项目的 pom 文件...
插件"maven-sufefire-plugin"被添加了2次这样
<project>
<profiles>
[...]
<profile>
<id>unit-test</id>
<plugins>
[...]
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>
${argLine} -Dfile.encodeing=utf-8 -Duser.timezone=UTC
</argLine>
</configuration>
</plugin>
[...]
<project>
<build>
<plugins>
[...]
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>
-Dfile.encodeing=utf-8 -Duser.timezone=UTC
</argLine>
</configuration>
</plugin>
[...]
但是 属性 ${argLine}
根本没有在 pom 文件中设置。
所以我引入了一个新的 属性 <argLine>
并将这些参数放在那里……瞧,它起作用了……
不知道为什么 hashcode 方法会抛出异常,但也许这对其他人也有帮助:-)