Проблема с издевательством над tokenService в Spock для OAuth2 - PullRequest
0 голосов
/ 29 марта 2020

Недавно я написал несколько тестов REST для моего API в JUnit. API защищен с помощью OAuth2. Моей целью было высмеять всю безопасность OAuth2 вместе с фальшивым токеном. Мне удалось сделать это при использовании JUnits, но я хотел бы использовать Spock из-за его приятных возможностей.

Тестовый класс для JUnit (который прекрасно работает):

@RunWith(SpringRunner.class)
@SpringBootTest(
    webEnvironment = SpringBootTest.WebEnvironment.MOCK,
    classes = AccountServiceApplication.class)
@AutoConfigureMockMvc
@ActiveProfiles("test")
public class AccountControllerRestTest {

protected final String TOKEN_VALUE = "test.fake.jwt";

@Autowired
protected MockMvc mockMvc;

@MockBean
private DefaultTokenServices defaultTokenServices;

@Before
public void setUp() {
    when(defaultTokenServices.loadAuthentication(TOKEN_VALUE))
            .thenAnswer(invocation -> SecurityContextHolder.getContext().getAuthentication());
}

@Test
@WithMockOAuth2User(
        client = @WithMockOAuth2Client(
                authorities = "ROLE_ADMIN"),
        user = @WithMockUser(
                username = "random",
                authorities = "ROLE_ADMIN"))
public void getAccountRestTest() throws Exception {
    ResultActions result = mockMvc.perform(MockMvcRequestBuilders.get("/someUrl/")
            .header("Authorization", "Bearer " + TOKEN_VALUE))
            .andExpect(status().isOk());
}

}

Однако этот тестовый класс для Спока дает мне следующую ошибку:

Caused by: java.lang.IllegalStateException: Unable to register mock bean org.springframework.security.oauth2.provider.token.ResourceServerTokenServices expected a single matching bean to replace but found [remoteTokenServices, tokenServices]

И код:

package com.sm.hupina.accountservice.rest

@SpringBootTest(
    webEnvironment = SpringBootTest.WebEnvironment.MOCK,
    classes = AccountServiceApplication.class)
@AutoConfigureMockMvc
@ActiveProfiles("test")
class AccountControllerRestSpec extends Specification {

protected static final String TOKEN_VALUE = "test.fake.jwt"

@SpringBean
private DefaultTokenServices defaultTokenServices = Mock()

@Autowired
protected MockMvc mvc

def setup() {
    defaultTokenServices.loadAuthentication(TOKEN_VALUE) >> SecurityContextHolder.getContext().getAuthentication()
}

@WithMockOAuth2User(
        client = @WithMockOAuth2Client(
                authorities = "ROLE_ADMIN"),
        user = @WithMockUser(
                username = "random",
                authorities = "ROLE_ADMIN"))
def 'should return 200 '() {
    when:

    def results = mvc.perform(MockMvcRequestBuilders.get("/someUrl/")
            .header("Authorization", "Bearer " + TOKEN_VALUE))


    then: 'server returns 200 code (ok)'
    assert results.status == 200: 'response code should be 200'
}

}

Я пытался с @WebMvcTest также, все еще не работал. Во время отладки похоже, что @SpringBean может создавать фиктивный бин (например, с произвольным именем и аннотацией @Qualified), но не может заменить существующий. Однако использование @MockBean в JUnit похоже на его замену и работает нормально. Буду признателен за какое-то решение этого.

...