Spring启动微服务- Spring安全- ServiceTest和ControllerTest为JUnit抛出jav



我在一个spring启动微服务(订单服务)的服务测试和控制器测试中运行任何测试方法都有问题。

在我完成服务和控制器后,我试图编写他们的测试方法,但我在那里有一个问题。

我该如何修复它?

这是订单服务的安全配置?

@Configuration
@EnableWebSecurity(debug = true)
@EnableGlobalMethodSecurity(prePostEnabled = true)
@RequiredArgsConstructor
public class SecurityConfig {
//
private final JwtAuthenticationEntryPoint authenticationEntryPoint;
private final JWTAccessDeniedHandler accessDeniedHandler;
private final JwtAuthenticationFilter jwtAuthenticationFilter;

@Bean(BeanIds.AUTHENTICATION_MANAGER)
public AuthenticationManager authenticationManager(final AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.csrf().disable()
.authorizeRequests()
.antMatchers(HttpMethod.POST, "/order/**").hasRole("USER")
.antMatchers(HttpMethod.GET, "/order/**").hasRole("USER")
.and()
.authorizeRequests().anyRequest().authenticated()
.and()
.formLogin().disable()
.httpBasic().disable()
.exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint)
.accessDeniedHandler(accessDeniedHandler)
.and()
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
.build();
}
@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
return (web)
-> web.ignoring().antMatchers("/authenticate/signup", "/authenticate/login", "/authenticate/refreshtoken");
}
}

下面是OrderServiceTest的一个测试方法

@DisplayName("Get Order - Success Scenario")
@Test
void test_When_Order_Success() {

//Mocking
Order order = getMockOrder();
when(orderRepository.findById(anyLong()))
.thenReturn(Optional.of(order));

when(restTemplate.getForObject(
"http://PRODUCT-SERVICE/product/" + order.getProductId(),
ProductResponse.class
)).thenReturn(getMockProductResponse());

when(restTemplate.getForObject(
"http://PAYMENT-SERVICE/payment/order/" + order.getId(),
PaymentResponse.class
)).thenReturn(getMockPaymentResponse());

//Actual
OrderResponse orderResponse = orderService.getOrderDetails(1);

//Verification
verify(orderRepository, times(1)).findById(anyLong());
verify(restTemplate, times(1)).getForObject(
"http://PRODUCT-SERVICE/product/" + order.getProductId(),
ProductResponse.class);
verify(restTemplate, times(1)).getForObject(
"http://PAYMENT-SERVICE/payment/order/" + order.getId(),
PaymentResponse.class);

//Assert
assertNotNull(orderResponse);
assertEquals(order.getId(), orderResponse.getOrderId());
}

下面是OrderControllerTest的一个测试方法。

@Test
@DisplayName("Place Order -- Success Scenario")
@WithMockUser(username = "User", authorities = { "ROLE_USER" })
void test_When_placeOrder_DoPayment_Success() throws Exception {
OrderRequest orderRequest = getMockOrderRequest();
String jwt = getJWTTokenForRoleUser();
MvcResult mvcResult
= mockMvc.perform(MockMvcRequestBuilders.post("/order/placeorder")
.contentType(MediaType.APPLICATION_JSON_VALUE)
.header("Authorization", "Bearer " + jwt)
.content(objectMapper.writeValueAsString(orderRequest)))
.andExpect(MockMvcResultMatchers.status().isOk())
.andReturn();
String orderId = mvcResult.getResponse().getContentAsString();
Optional<Order> order = orderRepository.findById(Long.valueOf(orderId));
assertTrue(order.isPresent());
Order o = order.get();
assertEquals(Long.parseLong(orderId), o.getId());
assertEquals("PLACED", o.getOrderStatus());
assertEquals(orderRequest.getTotalAmount(), o.getAmount());
assertEquals(orderRequest.getQuantity(), o.getQuantity());
}

下面是我运行服务测试和控制器的任何方法时的错误。

java.lang.StackOverflowError
at java.base/java.lang.Throwable.getOurStackTrace(Throwable.java:861)
at java.base/java.lang.Throwable.getStackTrace(Throwable.java:853)
at ch.qos.logback.classic.spi.ThrowableProxy.<init>(ThrowableProxy.java:79)
...
...

运行应用程序,

1)运行Service registry (Eureka Server)

2)运行config server 3)在docker 上运行zipkin和redis
docker run -d -p 9411:9411 openzipkin/zipkin
docker run -d --name redis -p 6379:6379 redis
4)运行api gateway 5)运行其他服务

这是repo: Link

这是服务测试的结果链接

这是控制器测试的结果链接

编辑代替

@Bean(BeanIds.AUTHENTICATION_MANAGER)
public AuthenticationManager authenticationManager(final AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}

@Bean
public AuthenticationManager authenticationManager(List<AuthenticationProvider> myAuthenticationProviders) {
return new ProviderManager(myAuthenticationProviders);
}

在订单服务的安全配置。

错误信息如下所示。

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'authenticationManager' defined in class path resource [com/microservice/orderservice/config/SecurityConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.authentication.AuthenticationManager]: Factory method 'authenticationManager' threw exception; nested exception is java.lang.IllegalArgumentException: A parent AuthenticationManager or a list of AuthenticationProviders is required
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:658) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:638) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1352) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1195) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:955) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) ~[spring-context-5.3.22.jar:5.3.22]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.22.jar:5.3.22]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) ~[spring-boot-2.7.3.jar:2.7.3]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:734) ~[spring-boot-2.7.3.jar:2.7.3]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408) ~[spring-boot-2.7.3.jar:2.7.3]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) ~[spring-boot-2.7.3.jar:2.7.3]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) ~[spring-boot-2.7.3.jar:2.7.3]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) ~[spring-boot-2.7.3.jar:2.7.3]
at com.microservice.orderservice.OrderServiceApplication.main(OrderServiceApplication.java:15) ~[classes/:na]
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.authentication.AuthenticationManager]: Factory method 'authenticationManager' threw exception; nested exception is java.lang.IllegalArgumentException: A parent AuthenticationManager or a list of AuthenticationProviders is required
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653) ~[spring-beans-5.3.22.jar:5.3.22]
... 19 common frames omitted
Caused by: java.lang.IllegalArgumentException: A parent AuthenticationManager or a list of AuthenticationProviders is required
at org.springframework.util.Assert.isTrue(Assert.java:121) ~[spring-core-5.3.22.jar:5.3.22]
at org.springframework.security.authentication.ProviderManager.checkState(ProviderManager.java:138) ~[spring-security-core-5.7.3.jar:5.7.3]
at org.springframework.security.authentication.ProviderManager.<init>(ProviderManager.java:129) ~[spring-security-core-5.7.3.jar:5.7.3]
at org.springframework.security.authentication.ProviderManager.<init>(ProviderManager.java:117) ~[spring-security-core-5.7.3.jar:5.7.3]
at com.microservice.orderservice.config.SecurityConfig.authenticationManager(SecurityConfig.java:42) ~[classes/:na]
at com.microservice.orderservice.config.SecurityConfig$$EnhancerBySpringCGLIB$$83744c5.CGLIB$authenticationManager$0(<generated>) ~[classes/:na]
at com.microservice.orderservice.config.SecurityConfig$$EnhancerBySpringCGLIB$$83744c5$$FastClassBySpringCGLIB$$8d59030c.invoke(<generated>) ~[classes/:na]
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244) ~[spring-core-5.3.22.jar:5.3.22]
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331) ~[spring-context-5.3.22.jar:5.3.22]
at com.microservice.orderservice.config.SecurityConfig$$EnhancerBySpringCGLIB$$83744c5.authenticationManager(<generated>) ~[classes/:na]
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:578) ~[na:na]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.3.22.jar:5.3.22]
... 20 common frames omitted

这个错误很可能是由将AuthenticationManager声明为@Bean引起的。在您的测试类中试试:

@MockBean
private AuthenticationManager _authenticationManager;

也就是说,Spring Security团队不建议以这种方式公开AuthenticationManager,请参阅Spring issue #29215中的评论

相关内容

  • 没有找到相关文章

最新更新