Skip to content

Make test slices' type exclude filters public #18746

@rainbow702

Description

@rainbow702

I want to test a REST Controller in my spring boot project, I wrote the following code:

@RunWith(SpringJUnit4ClassRunner.class)
@WebMvcTest(MetaInfoController.class)
@TypeExcludeFilters({TypeExcludeFilterForControllerTest.class})
public class MetaInfoControllerTest {
   // ....
}

The TypeExcludeFilterForControllerTest class is as follows:

public class TypeExcludeFilterForControllerTest extends TypeExcludeFilter {

        private static final List<String> EXCLUDE_CLASS_NAMES = Arrays.asList(WebConfig.class.getName(), MyCasAuthenticationFilter.class.getName());

        @Override
        public boolean match(final MetadataReader metadataReader, final MetadataReaderFactory metadataReaderFactory) throws IOException {
            return EXCLUDE_CLASS_NAMES.contains(metadataReader.getClassMetadata().getClassName());
        }
    }

The purpose I did this is to prevent some classes from being loaded to spring application context, in addition to @WebMvcTest.
But, when I run the tests, I got the following error:

Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'metaInfoService' defined in file [/xx/xx/MetaInfoService.class]: Unsatisfied dependency expressed through constructor parameter 1; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'metaMapper' defined in file [/xx/xx/metaMapper.class]:
// ... more

It seems that the @TypeExcludeFilters(WebMvcTypeExcludeFilter.class) which is inside the @WebMvcTest does not work. To demonstrate my opinion, I debugged into the source code, and I found the reason.

During the test context building process, one step is to create a context customizer for TypeExcludeFiltersContextCustomizer, and this is done by calling the createContextCustomizer() method of TypeExcludeFiltersContextCustomizerFactory class. This method calls the AnnotatedElementUtils.findMergedAnnotation() to get the @TypeExcludeFilters defination. According to the java doc of findMergedAnnotation(), it will only get the first found @TypeExcludeFilters defination and return it, so, the @TypeExcludeFilters(WebMvcTypeExcludeFilter.class) of @WebMvcTest is ignored.

To resolve this problem, I tried to add the WebMvcTypeExcludeFilter.class to mine outside @TypeExcludeFilters defination like this:

@TypeExcludeFilters({TypeExcludeFilterForControllerTest.class, WebMvcTypeExcludeFilter.class})

But I found that the access modifier of WebMvcTypeExcludeFilter is Default, so it can not be accessed from outside the package.

So my question is: Is it possible to change 'WebMvcTypeExcludeFilter' class to be public?

Or, is there any other workaround solution?

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions