【发布时间】:2019-07-10 09:47:55
【问题描述】:
我有一个使用 spring boot 2 构建的项目(数据、休息、安全......),所以在项目中我有这样的休息控制器:
@RestController
class ProductController {
private final ProductService productService;
private final ProductConverter productConverter;
private final UserService userService;
@Autowired
ProductController(ProductService productService,
ProductConverter productConverter,
UserService userService) {
this.productService = productService;
this.productConverter = productConverter;
this.userService = userService;
}
@GetMapping(EndpointPath.PRODUCTS)
PageableProductsDTO getProducts(Principal principal, Pageable pageable) {
return productService.getUsersProducts(principal.getName(), pageable);
}
@PostMapping(EndpointPath.PRODUCT)
ResponseEntity<?> createNewProduct(@Valid @RequestBody ProductDetailsDto productDetailsDto, Principal principal) {
productService.saveProduct(productConverter.createFrom(productDetailsDto), principal.getName());
return ResponseEntity.status(HttpStatus.CREATED).build();
}
}
还有安全配置:
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
private final RESTLogoutSuccessHandler restLogoutSuccessHandler;
@Autowired
public ResourceServerConfig(RESTLogoutSuccessHandler restLogoutSuccessHandler) {
this.restLogoutSuccessHandler = restLogoutSuccessHandler;
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.anonymous()
.disable()
.logout()
.logoutUrl(EndpointPath.SIGN_OUT)
.logoutSuccessHandler(restLogoutSuccessHandler)
.and()
.authorizeRequests()
.antMatchers(GET, EndpointPath.PRODUCTS).authenticated()
.antMatchers(POST, EndpointPath.PRODUCT).authenticated()
.and()
.exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());
}
}
我还用这样的单元测试介绍了 ProductController:
@ExtendWith({SpringExtension.class, MockitoExtension.class})
@ContextConfiguration(classes = {MessageSourceConfiguration.class})
@MockitoSettings(strictness = Strictness.LENIENT)
class ProductControllerTest {
private MockMvc mockMvc;
@Autowired
private MessageSource messageSource;
@Mock
private ProductService productService;
@Mock
private ProductConverter productConverter;
@Mock
private UserService userService;
@BeforeEach
void setUp() {
mockMvc = MockMvcBuilders.standaloneSetup(new ProductController(productService, productConverter, userService))
.setCustomArgumentResolvers(new PageableHandlerMethodArgumentResolver())
.setControllerAdvice(new ControllerAdvice(messageSource)).build();
}
@Test
void shouldReturnSetOfProducts() throws Exception {
// Given
String authenticatedUserEmail = "email@g.com";
when(productService.getUsersProducts(eq(authenticatedUserEmail), ArgumentMatchers.any(Pageable.class))).thenReturn(new PageableProductsDTO(new PageImpl<>(
List.of(new ProductDetailsDto("1234", "name", 1), new ProductDetailsDto("12345", "name 2", 2)))));
// When - Then
mockMvc.perform(get(EndpointPath.PRODUCTS).principal(() -> authenticatedUserEmail).accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
.andExpect(jsonPath("$.productDtos.content", hasSize(2)))
.andExpect(jsonPath("$.productDtos.totalPages", is(1)))
.andExpect(jsonPath("$.productDtos.totalElements", is(2)))
.andExpect(jsonPath("$.productDtos.content.[*].barcode", containsInAnyOrder("1234", "12345")))
.andExpect(jsonPath("$.productDtos.content.[*].name", containsInAnyOrder("name", "name 2")))
.andExpect(jsonPath("$.productDtos.content.[*].price", containsInAnyOrder(1, 2)));
}
}
除了单元测试之外,我还想确保端点 EndpointPath.PRODUCTS 是安全的。有人知道如何为此编写单元测试吗?例如:用户未通过身份验证/授权时的预期状态 401/403。
【问题讨论】:
-
编写一个没有身份验证的案例,触发 API 并期望状态为 -401/403 并测试您的 401/403 响应
标签: java spring-boot junit spring-security junit5