Недавно я написал несколько тестов 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 похоже на его замену и работает нормально. Буду признателен за какое-то решение этого.