Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Duplicate annotation exception with MockMvc and method-level annotations #11436

Closed
theseion opened this issue Jun 24, 2022 · 6 comments
Closed
Assignees
Labels
in: test An issue in spring-security-test status: feedback-provided Feedback has been provided type: bug A general bug
Milestone

Comments

@theseion
Copy link

theseion commented Jun 24, 2022

Describe the bug
While upgrading from Spring Boot 2.5.6 to 2.7.1 I noticed an issue with MockMvc and method-level @PreAuthorize annotations. The issue appears to be that the anonymous class that Mockito creates includes the same annotations on the methods as the original class. The new checks for duplicate annotations (introduced in 5.6) now see the same annotation twice, once on the original method and once on the anonymous override.

To Reproduce
This is my test setup (only relevant parts included):

@RequiredArgsConstructor
@SpringBootTest
class MyTestClass {
  @SpyBean private final ImportController importController;
  private MockMvc mockMvc;

  @BeforeEach
   void setUp() {
    mocks = MockitoAnnotations.openMocks(this);
    mockMvc = MockMvcBuilders.webAppContextSetup(context).apply(springSecurity()).build();
  }

  @AfterEach
  void tearDown() throws Exception {
    mocks.close();
  }

  @Test
  void uploadFile() throws Exception {
      var file = new MockMultipartFile(/*...*/);
    mockMvc
        .perform(
            multipart("/import")
                .file(file)
                .with(oidcLogin())
                .with(csrf())
                .with(user("user").roles("EXPERT")))
        .andExpect(status().isOk());

   /* verification etc. */
  }
}

Running this test produces AnnotationConfigurationException in AuthorizationAnnotationUtils#findUniqueAnnotation due to a duplicate @PreAuthorize annotation on the uploadFile() method:

  @PreAuthorize("hasRole('EXPERT')")
  public UploadFileDto uploadFile(/*...*/) {
     /*...*/
  }

Expected behavior
Identical annotations on overridden methods should be possible and not throw an exception.

Sample

MWE: https://github.com/theseion/spring-security-mwe

Versions (Spring Boot 5.7.2):
Spring Security: 5.7.2
Spring Boot Test: 2.7.1
Spring Test 5.3.21

@theseion theseion added status: waiting-for-triage An issue we've not yet triaged type: bug A general bug labels Jun 24, 2022
@marcusdacoregio
Copy link
Contributor

Hi @theseion, thanks for reaching out.

Before getting into the actual issue, I'd like to clarify if you are trying to do a unit or integration test?
I'm asking that because I see @SpringBootTest which is normally used to do integration tests, but then you are spying on your bean and will probably check if it is calling the other beans. I would like to suggest a change if that's the case:

@WebMvcTest(ImportController.class)
class MyTestClass {
  @MockBean private MyBeanService myBeanService;
  private MockMvc mockMvc;

  @BeforeEach
   void setUp() {
    mocks = MockitoAnnotations.openMocks(this);
    mockMvc = MockMvcBuilders.webAppContextSetup(context).apply(springSecurity()).build();
  }

  @AfterEach
  void tearDown() throws Exception {
    mocks.close();
  }

  @Test
  void uploadFile() throws Exception {
      var file = new MockMultipartFile(/*...*/);
    mockMvc
        .perform(
            multipart("/import")
                .file(file)
                .with(oidcLogin())
                .with(csrf())
                .with(user("user").roles("EXPERT")))
        .andExpect(status().isOk());

   /* verification etc. */
    // verify(myBeanService).method(...);
  }
}

Using @WebMvcTest you can test your controller isolated from the other components. If you still want to use the former setup, please provide a reproducible example.

@marcusdacoregio marcusdacoregio added status: waiting-for-feedback We need additional information before we can continue in: test An issue in spring-security-test and removed status: waiting-for-triage An issue we've not yet triaged labels Jun 27, 2022
theseion pushed a commit to theseion/spring-security-mwe that referenced this issue Jun 28, 2022
theseion added a commit to theseion/spring-security-mwe that referenced this issue Jun 28, 2022
theseion added a commit to theseion/spring-security-mwe that referenced this issue Jun 28, 2022
@theseion
Copy link
Author

Thanks for getting back to me @marcusdacoregio. It's really an integration test and I need to pull up the entire context. I've updated the issue with a link to an MWE.

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Jun 28, 2022
@saugion
Copy link

saugion commented Jul 14, 2023

I'm having the same issue during the migration to spring boot 3.1.1, findUniqueAnnotation is throwing an exception saying it finds twice the @PreAuthorize annotation. After debugging I see twice the same proxy with the same method, it should not happen

@marcusdacoregio
Copy link
Contributor

I believe that this is the same problem as #13490

@saugion
Copy link

saugion commented Jul 14, 2023

Yes, it seems so. In my case is PreAuthorize but the case is the same

@jzheaux
Copy link
Contributor

jzheaux commented Jun 5, 2024

Thanks for the report, @theseion. I believe this was addressed in #13625.

It updated the sample to the latest and saw the behavior corrected. The fix should already be available in the latest 5.8+ and 6.2+

@jzheaux jzheaux closed this as completed Jun 5, 2024
@jzheaux jzheaux added this to the 5.8.9 milestone Jun 5, 2024
@jzheaux jzheaux self-assigned this Jun 5, 2024
@jzheaux jzheaux moved this to Done in Spring Security Team Jun 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: test An issue in spring-security-test status: feedback-provided Feedback has been provided type: bug A general bug
Projects
Status: Done
Development

No branches or pull requests

5 participants