From e04ace89b9dd04cb1dadc527da1fdf6f0b606ab8 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 19 Jan 2017 15:19:50 +0000 Subject: [PATCH] Fix LinkageError with ExpectedException and FilteredClassPathRunner Previously, when the ExpectedException JUnit rule was used with FilteredClassPathRunner a LinkageError would occur if any of ExpectedException's methods that take a Hamcrest Matcher were called. This was due to the FilteredClassLoader delegating loading of org.junit classes to its parent but not org.hamcrest classes. This resulted in JUnit classes loading one version of the Hamcrest class and the test class loading another. This commit ensures that both the JUnit classes and the test class use the same version of Hamcrest classes by also delegating the loading of org.hamcrest classes to FilteredClassLoader's parent. --- .../boot/testutil/FilteredClassPathRunner.java | 4 ++-- .../testutil/FilteredClassPathRunnerTests.java | 14 +++++++++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/spring-boot/src/test/java/org/springframework/boot/testutil/FilteredClassPathRunner.java b/spring-boot/src/test/java/org/springframework/boot/testutil/FilteredClassPathRunner.java index b7ca5f5152..cedefb547b 100644 --- a/spring-boot/src/test/java/org/springframework/boot/testutil/FilteredClassPathRunner.java +++ b/spring-boot/src/test/java/org/springframework/boot/testutil/FilteredClassPathRunner.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2016 the original author or authors. + * Copyright 2012-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -264,7 +264,7 @@ public class FilteredClassPathRunner extends BlockJUnit4ClassRunner { @Override public Class loadClass(String name) throws ClassNotFoundException { - if (name.startsWith("org.junit")) { + if (name.startsWith("org.junit") || name.startsWith("org.hamcrest")) { return this.junitLoader.loadClass(name); } return super.loadClass(name); diff --git a/spring-boot/src/test/java/org/springframework/boot/testutil/FilteredClassPathRunnerTests.java b/spring-boot/src/test/java/org/springframework/boot/testutil/FilteredClassPathRunnerTests.java index 73ef93cb80..ff461a4e0d 100644 --- a/spring-boot/src/test/java/org/springframework/boot/testutil/FilteredClassPathRunnerTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/testutil/FilteredClassPathRunnerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2016 the original author or authors. + * Copyright 2012-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,10 +16,13 @@ package org.springframework.boot.testutil; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import static org.assertj.core.api.Assertions.assertThat; +import static org.hamcrest.CoreMatchers.isA; /** * Tests for {@link FilteredClassPathRunner} @@ -33,6 +36,9 @@ public class FilteredClassPathRunnerTests { private static final String EXCLUDED_RESOURCE = "META-INF/services/" + "javax.validation.spi.ValidationProvider"; + @Rule + public ExpectedException thrown = ExpectedException.none(); + @Test public void entriesAreFilteredFromTestClassClassLoader() { assertThat(getClass().getClassLoader().getResource(EXCLUDED_RESOURCE)).isNull(); @@ -44,4 +50,10 @@ public class FilteredClassPathRunnerTests { .getResource(EXCLUDED_RESOURCE)).isNull(); } + @Test + public void testsThatUseHamcrestWorkCorrectly() { + this.thrown.expect(isA(IllegalStateException.class)); + throw new IllegalStateException(); + } + }