3

I have multiple security test classes where I am testing authorization to different REST endpoints, and I would like to mock the beans of all the repositories that ApplicationContext will spin up. I have the tests running and everything works correctly, but I'd like to not duplicate my @MockBeans in every security test class.

I've tried creating a configuration class and putting the MockBeans there, but I receive a 404 error.

The current test class is setup like this and it works, but I have to duplicate the @MockBeans() in each class:

@WebMvcTest(value = [ScriptController, SecurityConfiguration, ScriptPermissionEvaluator])
@ExtendWith(SpringExtension)
@MockBeans([@MockBean(ObjectRepository), @MockBean(ChannelRepository), 
@MockBean(ChannelSubscriberRepository)])
@ActiveProfiles("test")
class ScriptControllerSecurityTest extends Specification

I'd like to setup a configuration class like this and use it inside of my test class with @ContextConfiguration(classes = MockRepositoryConfiguration) in the test class.

@Configuration
@MockBeans([@MockBean(ObjectRepository), @MockBean(ChannelRepository), 
@MockBean(ChannelSubscriberRepository)])
class MockRepositoryConfiguration
{}
Droem19
  • 59
  • 1
  • 8
  • Have you tried adding the annotations to `Specification` itself? – João Dias Nov 09 '21 at 18:48
  • @JoãoDias Specification in this class is coming from our spock dependency, so I don't think that is what I am looking for. https://spockframework.org/spock/javadoc/1.0/spock/lang/Specification.html – Droem19 Nov 09 '21 at 19:01
  • Ah ok, didn't know that. Have you tried a custom meta-annotation then? – João Dias Nov 09 '21 at 19:03
  • @JoãoDias I have not - I'm not crazy familiar with Spring, so im not quite sure what the best solution is - if you have an idea of how that might work/be implemented I could try. – Droem19 Nov 09 '21 at 19:09

1 Answers1

4

Try creating a custom meta-annotation as follows:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.Type)
@MockBeans([@MockBean(ObjectRepository), @MockBean(ChannelRepository), 
@MockBean(ChannelSubscriberRepository)])
public @interface CustomMockBeans {
}

And then annotate your test class with it:

@WebMvcTest(value = [ScriptController, SecurityConfiguration, ScriptPermissionEvaluator])
@ExtendWith(SpringExtension)
@CustomMockBeans
@ActiveProfiles("test")
class ScriptControllerSecurityTest extends Specification
João Dias
  • 16,277
  • 6
  • 33
  • 45
  • With some initial testing - this seems to be working! I'm curious what the difference in this is compared to using @ContextConfiguration? Is there some backend spring magic that is making the mocked beans behave differently when using this? – Droem19 Nov 09 '21 at 19:53
  • 1
    I guess that `@ContextConfiguration` is not scanned in a `@WebMvcTest` given that this will only create a partial Spring context. Maybe it only works with fully-fledged integration tests with `@SpringBootTest`. But this is just a guess. – João Dias Nov 09 '21 at 20:00
  • That seems like a good guess. Either way I will take it. Thank you! – Droem19 Nov 09 '21 at 20:29
  • You are welcome. Consider upvoting the answer and accept it as the answer so that your question can be ”closed” and others can benefit from it and easily understand which could be a possible solution for similar questions ;) Thanks! – João Dias Nov 09 '21 at 20:32