当前位置: 首页 > 知识库问答 >
问题:

WebSecurityConfiguration antMatcher() 在集成测试中不忽略外部 API 的特定 url

萧渝
2023-03-14

我正在Spring Boot应用程序中实施AWS Cognito安全机制。启用安全性后,我遇到了已经存在的外部API联调问题。作为测试结果,我收到了一个错误:

2020-11-15 18:18:20.033 ERROR 12072 --- [ main]. c. s. f. AwsCognitoJwtAuthenticationFilter:无效操作,找不到令牌MockHttpServlet响应:状态=401错误消息=null Headers=[Access-Control-Allow-Origin:"*", Access-Control-Allow-方法:"POST, GET, OPTIONS, PUT, DELETE", Access-Control-Max-age:"3600", Access-Control-Allow-凭据:"true", Access-Control-Allow-Headers:"Content-type, Authorization", Content-Type:"application/json"]Content type=application/json Body={"data": null,"异常":{"Mess":"JWT Handle异常","httpstatusCode":"INTERNAL_SERVER_ERROR","详细信息": null}

我的WebSecurityConfiguration看起来像:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableTransactionManagement
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

  private CustomAuthenticationProvider authProvider;
  private AwsCognitoJwtAuthenticationFilter awsCognitoJwtAuthenticationFilter;
  private AccountControllerExceptionHandler exceptionHandler;
  private static final String LOGIN_URL = "/auth/login";
  private static final String LOGOUT_URL = "/auth/signOut";

  @Autowired
  public WebSecurityConfiguration(
      CustomAuthenticationProvider authProvider,
      AwsCognitoJwtAuthenticationFilter awsCognitoJwtAuthenticationFilter,
      AccountControllerExceptionHandler exceptionHandler) {
    this.authProvider = authProvider;
    this.awsCognitoJwtAuthenticationFilter = awsCognitoJwtAuthenticationFilter;
    this.exceptionHandler = exceptionHandler;
  }

  public WebSecurityConfiguration() {
    super(true);
  }

  @Override
  protected void configure(AuthenticationManagerBuilder auth) {
    auth.authenticationProvider(authProvider).eraseCredentials(false);
  }

  @Bean
  @Override
  public AuthenticationManager authenticationManagerBean() throws Exception {
    return super.authenticationManagerBean();
  }

  @Override
  public void configure(WebSecurity web) {
    // TokenAuthenticationFilter will ignore the below paths
    web.ignoring().antMatchers("/auth");
    web.ignoring().antMatchers("/auth/**");
    web.ignoring().antMatchers("/v2/api-docs");
    web.ignoring().antMatchers(GET, "/nutrition/api/**");
    web.ignoring().antMatchers(GET, "/**");
    web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
  }

  @Override
  protected void configure(HttpSecurity httpSecurity) throws Exception {
    httpSecurity
        .addFilterAfter(corsFilter(), ExceptionTranslationFilter.class)
        .exceptionHandling()
        .authenticationEntryPoint(new SecurityAuthenticationEntryPoint())
        .accessDeniedHandler(new RestAccessDeniedHandler())
        .and()
        .anonymous()
        .and()
        .sessionManagement()
        .sessionCreationPolicy(STATELESS)
        .and()
        .authorizeRequests()
        .antMatchers("/auth")
        .permitAll()
        .anyRequest()
        .authenticated()
        .and()
        .addFilterBefore(
            awsCognitoJwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
        .formLogin(formLogin -> formLogin.loginProcessingUrl(LOGIN_URL).failureHandler(exceptionHandler))
        .logout(logout -> logout.permitAll().logoutUrl(LOGOUT_URL))
        .csrf(AbstractHttpConfigurer::disable);
  }

  private CorsFilter corsFilter() {
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

    CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.addAllowedOrigin("*");
    config.addAllowedHeader(ORIGIN);
    config.addAllowedHeader(CONTENT_TYPE);
    config.addAllowedHeader(ACCEPT);
    config.addAllowedHeader(AUTHORIZATION);
    config.addAllowedMethod(GET);
    config.addAllowedMethod(PUT);
    config.addAllowedMethod(POST);
    config.addAllowedMethod(OPTIONS);
    config.addAllowedMethod(DELETE);
    config.addAllowedMethod(PATCH);
    config.setMaxAge(3600L);

    source.registerCorsConfiguration("/v2/api-docs", config);
    source.registerCorsConfiguration("/**", config);

    return new CorsFilter();
  }
}

一个wsC ogni到J wt身份验证过滤器

@Slf4j
public class AwsCognitoJwtAuthenticationFilter extends OncePerRequestFilter {

  private static final String ERROR_OCCURRED_WHILE_PROCESSING_THE_TOKEN =
      "Error occured while processing the token";
  private static final String INVALID_TOKEN_MESSAGE = "Invalid Token";

  private final AwsCognitoIdTokenProcessor awsCognitoIdTokenProcessor;

  @Autowired private ApplicationContext appContext;

  public AwsCognitoJwtAuthenticationFilter(AwsCognitoIdTokenProcessor awsCognitoIdTokenProcessor) {
    this.awsCognitoIdTokenProcessor = awsCognitoIdTokenProcessor;
  }

  private void createExceptionResponse(
      ServletRequest request, ServletResponse response, CognitoException exception)
      throws IOException {
    HttpServletRequest req = (HttpServletRequest) request;
    ExceptionController exceptionController;
    ObjectMapper objMapper = new ObjectMapper();

    exceptionController = appContext.getBean(ExceptionController.class);
    ResponseData<Object> responseData = exceptionController.handleJwtException(req, exception);

    HttpServletResponse httpResponse = CorsHelper.addResponseHeaders(response);

    final HttpServletResponseWrapper wrapper = new HttpServletResponseWrapper(httpResponse);
    wrapper.setStatus(HttpStatus.UNAUTHORIZED.value());
    wrapper.setContentType(APPLICATION_JSON_VALUE);
    wrapper.getWriter().println(objMapper.writeValueAsString(responseData));
    wrapper.getWriter().flush();
  }

  @Override
  protected void doFilterInternal(
      HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
      throws ServletException, IOException {
    Authentication authentication;
    try {
      authentication = awsCognitoIdTokenProcessor.getAuthentication(request);

      SecurityContextHolder.getContext().setAuthentication(authentication);

    } catch (BadJOSEException e) {
      SecurityContextHolder.clearContext();
      log.error(e.getMessage());
      createExceptionResponse(
          request,
          response,
          new CognitoException(
              INVALID_TOKEN_MESSAGE,
              CognitoException.INVALID_TOKEN_EXCEPTION_CODE,
              e.getMessage()));
      return;
    } catch (CognitoException e) {
      SecurityContextHolder.clearContext();
      log.error(e.getMessage());
      createExceptionResponse(
          request,
          response,
          new CognitoException(
              e.getErrorMessage(),
              CognitoException.INVALID_TOKEN_EXCEPTION_CODE,
              e.getDetailErrorMessage()));
      return;
    } catch (Exception e) {
      SecurityContextHolder.clearContext();
      log.error(e.getMessage());
      createExceptionResponse(
          request,
          response,
          new CognitoException(
              ERROR_OCCURRED_WHILE_PROCESSING_THE_TOKEN,
              CognitoException.INVALID_TOKEN_EXCEPTION_CODE,
              e.getMessage()));
      return;
    }

    filterChain.doFilter(request, response);
  }
}

一个wsC ogni到Id令牌处理器

@AllArgsConstructor
@NoArgsConstructor
public class AwsCognitoIdTokenProcessor {

  private static final String INVALID_TOKEN = "Invalid Token";
  private static final String NO_TOKEN_FOUND = "Invalid Action, no token found";

  private static final String ROLE_PREFIX = "ROLE_";
  private static final String EMPTY_STRING = "";

  private ConfigurableJWTProcessor<SecurityContext> configurableJWTProcessor;

  private AWSConfig jwtConfiguration;

  private String extractAndDecodeJwt(String token) {
    String tokenResult = token;

    if (token != null && token.startsWith("Bearer ")) {
      tokenResult = token.substring("Bearer ".length());
    }
    return tokenResult;
  }

  @SuppressWarnings("unchecked")
  public Authentication getAuthentication(HttpServletRequest request)
      throws ParseException, BadJOSEException, JOSEException {
    String idToken = request.getHeader(HTTP_HEADER);
    if (idToken == null) {
      throw new CognitoException(
          NO_TOKEN_FOUND,
          NO_TOKEN_PROVIDED_EXCEPTION,
          "No token found in Http Authorization Header");
    } else {

      idToken = extractAndDecodeJwt(idToken);
      JWTClaimsSet claimsSet;

      claimsSet = configurableJWTProcessor.process(idToken, null);

      if (!isIssuedCorrectly(claimsSet)) {
        throw new CognitoException(
            INVALID_TOKEN,
            INVALID_TOKEN_EXCEPTION_CODE,
            String.format(
                "Issuer %s in JWT token doesn't match cognito idp %s",
                claimsSet.getIssuer(), jwtConfiguration.getCognitoIdentityPoolUrl()));
      }

      if (!isIdToken(claimsSet)) {
        throw new CognitoException(
            INVALID_TOKEN, NOT_A_TOKEN_EXCEPTION, "JWT Token doesn't seem to be an ID Token");
      }

      String username = claimsSet.getClaims().get(USER_NAME_FIELD).toString();

      List<String> groups = (List<String>) claimsSet.getClaims().get(COGNITO_GROUPS);
      List<GrantedAuthority> grantedAuthorities =
          convertList(
              groups, group -> new SimpleGrantedAuthority(ROLE_PREFIX + group.toUpperCase()));
      User user = new User(username, EMPTY_STRING, grantedAuthorities);
      return new CognitoJwtAuthentication(user, claimsSet, grantedAuthorities);
    }
  }

  private boolean isIssuedCorrectly(JWTClaimsSet claimsSet) {
    return claimsSet.getIssuer().equals(jwtConfiguration.getCognitoIdentityPoolUrl());
  }

  private boolean isIdToken(JWTClaimsSet claimsSet) {
    return claimsSet.getClaim("token_use").equals("id");
  }

  private static <T, U> List<U> convertList(List<T> from, Function<T, U> func) {
    return from.stream().map(func).collect(Collectors.toList());
  }
}

C ogni to J wt Auto Configuration

@Configuration
@Import(AWSConfig.class)
@ConditionalOnClass({AwsCognitoJwtAuthenticationFilter.class, AwsCognitoIdTokenProcessor.class})
public class CognitoJwtAutoConfiguration {

  private final AWSConfig jwtConfiguration;

  public CognitoJwtAutoConfiguration(AWSConfig jwtConfiguration) {
    this.jwtConfiguration = jwtConfiguration;
  }

  @Bean
  @Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
  public CognitoJwtIdTokenCredentialsHolder awsCognitoCredentialsHolder() {
    return new CognitoJwtIdTokenCredentialsHolder();
  }

  @Bean
  public AwsCognitoIdTokenProcessor awsCognitoIdTokenProcessor() {
    return new AwsCognitoIdTokenProcessor();
  }

  @Bean
  public CognitoJwtAuthenticationProvider jwtAuthenticationProvider() {
    return new CognitoJwtAuthenticationProvider();
  }

  @Bean
  public AwsCognitoJwtAuthenticationFilter awsCognitoJwtAuthenticationFilter() {
    return new AwsCognitoJwtAuthenticationFilter(awsCognitoIdTokenProcessor());
  }

  @SuppressWarnings({"rawtypes", "unchecked"})
  @Bean
  public ConfigurableJWTProcessor configurableJWTProcessor() throws MalformedURLException {
    ResourceRetriever resourceRetriever =
        new DefaultResourceRetriever(CONNECTION_TIMEOUT, READ_TIMEOUT);
    // https://cognito-idp.{region}.amazonaws.com/{userPoolId}/.well-known/jwks.json.
    URL jwkSetURL = new URL(jwtConfiguration.getJwkUrl());
    // Creates the JSON Web Key (JWK)
    JWKSource keySource = new RemoteJWKSet(jwkSetURL, resourceRetriever);
    ConfigurableJWTProcessor jwtProcessor = new DefaultJWTProcessor();
    JWSKeySelector keySelector = new JWSVerificationKeySelector(RS256, keySource);
    jwtProcessor.setJWSKeySelector(keySelector);
    return jwtProcessor;
  }

  @Bean
  public AWSCognitoIdentityProvider awsCognitoIdentityProvider() {
    return AWSCognitoIdentityProviderClientBuilder.standard()
        .withRegion(Regions.EU_CENTRAL_1)
        .withCredentials(getCredentialsProvider())
        .build();
  }

  @Bean
  public AWSCredentialsProvider getCredentialsProvider() {
    return new ClasspathPropertiesFileCredentialsProvider();
  }
}

我想将我的控制器URL排除在需要授权的endpoint之外。

基于视觉测试,控制器外观如下:

@RestController
@RequestMapping("/nutrition/api/")
class NutritionixApiController {

  private ProductFacadeImpl productFacadeImpl;

  public NutritionixApiController(
      ProductFacadeImpl productFacadeImpl) {
    this.productFacadeImpl = productFacadeImpl;
  }

  @GetMapping("/productDetails")
  public ResponseEntity<Set<RecipeIngredient>> productsDetails(@RequestParam String query) {
  //logic here
  }
}

我尝试在方法< code >配置(WebSecurity web)中将URL < code > "/nutrition/API/* * " 列入白名单,方法是添加:

web.ignoring().antMatchers(GET, "/nutrition/api/**");

web.ignoring().antMatchers(GET, "/**");

但没有期望的效果。我有点困惑,为什么忽略.antMatchers()不起作用,因此我将感谢有关如何解决上述问题的建议。

编辑

我回到了这个话题,但得到了同样的结果。在WebSecurityConfiguration中,我对@EnableGlobalMethodSecurity(prePostEnabled=true)进行了注释,以尝试不使用prePostEnabled=true但没有理想效果的配置。我对endpoint<code>/auth</code>也有同样的问题,这在配置中被忽略。我在教程之后进行了模式化,该教程正在运行并可在此处使用,但我对代码进行了一点重构,以使用@Autowired消除字段注入,但没有进行根本性的更改和逻辑隐藏。

此外,类CustomAuthenticationProvider看起来像:

@Component
@RequiredArgsConstructor
public class CustomAuthenticationProvider implements AuthenticationProvider {

  private final CognitoAuthenticationService cognitoService;

  @SuppressWarnings("unchecked")
  @Override
  public Authentication authenticate(Authentication authentication) {
    AuthenticationRequest authenticationRequest;

    if (authentication != null) {
      authenticationRequest = new AuthenticationRequest();
      Map<String, String> credentials = (Map<String, String>) authentication.getCredentials();
      authenticationRequest.setNewPassword(credentials.get(NEW_PASS_WORD_KEY));
      authenticationRequest.setPassword(credentials.get(PASS_WORD_KEY));
      authenticationRequest.setUsername(authentication.getName());

      SpringSecurityUser userAuthenticated = cognitoService.authenticate(authenticationRequest);
      if (userAuthenticated != null) {

        Map<String, String> authenticatedCredentials = new HashMap<>();
        authenticatedCredentials.put(ACCESS_TOKEN_KEY, userAuthenticated.getAccessToken());
        authenticatedCredentials.put(EXPIRES_IN_KEY, userAuthenticated.getExpiresIn().toString());
        authenticatedCredentials.put(ID_TOKEN_KEY, userAuthenticated.getIdToken());
        authenticatedCredentials.put(PASS_WORD_KEY, userAuthenticated.getPassword());
        authenticatedCredentials.put(REFRESH_TOKEN_KEY, userAuthenticated.getRefreshToken());
        authenticatedCredentials.put(TOKEN_TYPE_KEY, userAuthenticated.getTokenType());
        return new UsernamePasswordAuthenticationToken(
            userAuthenticated.getUsername(),
            authenticatedCredentials,
            userAuthenticated.getAuthorities());
      } else {
        return null;
      }
    } else {
      throw new UsernameNotFoundException("No application user for given username");
    }
  }

  @Override
  public boolean supports(Class<?> authentication) {
    return authentication.equals(UsernamePasswordAuthenticationToken.class);
  }
}

老实说,我不知道还能做些什么来解决这个不工作过滤器的问题。将不胜感激的帮助。

共有1个答案

顾光明
2023-03-14

虽然你指出了正确的忽略模式,Spring Security实际上忽略了过滤器,但我认为它仍然在执行,因为Spring可能正在再次注册安全链之外的过滤器,因为你在CognitoJwtAutoConfiguration中使用@Bean公开了过滤器。

为了避免这个问题,在您的代码中执行以下修改(基本上,确保您的过滤器只有一个实例)。首先,在< code > web security configuration 中:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableTransactionManagement
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

  private CustomAuthenticationProvider authProvider;
  private AccountControllerExceptionHandler exceptionHandler;
  private static final String LOGIN_URL = "/auth/login";
  private static final String LOGOUT_URL = "/auth/signOut";

  @Autowired
  public WebSecurityConfiguration(
      CustomAuthenticationProvider authProvider,
      AccountControllerExceptionHandler exceptionHandler) {
    // Do not provide AwsCognitoJwtAuthenticationFilter() as instance filed any more
    this.authProvider = authProvider;
    this.exceptionHandler = exceptionHandler;
  }

  public WebSecurityConfiguration() {
    super(true);
  }

  @Override
  protected void configure(AuthenticationManagerBuilder auth) {
    auth.authenticationProvider(authProvider).eraseCredentials(false);
  }

  @Bean
  @Override
  public AuthenticationManager authenticationManagerBean() throws Exception {
    return super.authenticationManagerBean();
  }

  @Override
  public void configure(WebSecurity web) {
    // TokenAuthenticationFilter will ignore the below paths
    web.ignoring().antMatchers("/auth");
    web.ignoring().antMatchers("/auth/**");
    web.ignoring().antMatchers("/v2/api-docs");
    web.ignoring().antMatchers(GET, "/nutrition/api/**");
    web.ignoring().antMatchers(GET, "/**");
    web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
  }

  @Override
  protected void configure(HttpSecurity httpSecurity) throws Exception {
    httpSecurity
        .addFilterAfter(corsFilter(), ExceptionTranslationFilter.class)
        .exceptionHandling()
        .authenticationEntryPoint(new SecurityAuthenticationEntryPoint())
        .accessDeniedHandler(new RestAccessDeniedHandler())
        .and()
        .anonymous()
        .and()
        .sessionManagement()
        .sessionCreationPolicy(STATELESS)
        .and()
        .authorizeRequests()
        .antMatchers("/auth")
        .permitAll()
        .anyRequest()
        .authenticated()
        .and()
        // Instantiate a new instance of the filter
        .addFilterBefore(
            awsCognitoJwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
        .formLogin(formLogin -> formLogin.loginProcessingUrl(LOGIN_URL).failureHandler(exceptionHandler))
        .logout(logout -> logout.permitAll().logoutUrl(LOGOUT_URL))
        .csrf(AbstractHttpConfigurer::disable);
  }

  private CorsFilter corsFilter() {
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

    CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.addAllowedOrigin("*");
    config.addAllowedHeader(ORIGIN);
    config.addAllowedHeader(CONTENT_TYPE);
    config.addAllowedHeader(ACCEPT);
    config.addAllowedHeader(AUTHORIZATION);
    config.addAllowedMethod(GET);
    config.addAllowedMethod(PUT);
    config.addAllowedMethod(POST);
    config.addAllowedMethod(OPTIONS);
    config.addAllowedMethod(DELETE);
    config.addAllowedMethod(PATCH);
    config.setMaxAge(3600L);

    source.registerCorsConfiguration("/v2/api-docs", config);
    source.registerCorsConfiguration("/**", config);

    return new CorsFilter();
  }

  // It will also be possible to inject AwsCognitoIdTokenProcessor
  private AwsCognitoJwtAuthenticationFilter awsCognitoJwtAuthenticationFilter() {
    return new AwsCognitoJwtAuthenticationFilter(new AwsCognitoIdTokenProcessor());
  }
}

您还需要从CognitoJwtAutoConfiguration中删除不必要的东西:

@Configuration
@Import(AWSConfig.class)
@ConditionalOnClass({AwsCognitoJwtAuthenticationFilter.class, AwsCognitoIdTokenProcessor.class})
public class CognitoJwtAutoConfiguration {

  private final AWSConfig jwtConfiguration;

  public CognitoJwtAutoConfiguration(AWSConfig jwtConfiguration) {
    this.jwtConfiguration = jwtConfiguration;
  }

  @Bean
  @Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
  public CognitoJwtIdTokenCredentialsHolder awsCognitoCredentialsHolder() {
    return new CognitoJwtIdTokenCredentialsHolder();
  }

  /* No longer needed
  @Bean
  public AwsCognitoIdTokenProcessor awsCognitoIdTokenProcessor() {
    return new AwsCognitoIdTokenProcessor();
  }*/

  @Bean
  public CognitoJwtAuthenticationProvider jwtAuthenticationProvider() {
    return new CognitoJwtAuthenticationProvider();
  }

  /* No longer needed
  @Bean
  public AwsCognitoJwtAuthenticationFilter awsCognitoJwtAuthenticationFilter() {
    return new AwsCognitoJwtAuthenticationFilter(awsCognitoIdTokenProcessor());
  }*/

  @SuppressWarnings({"rawtypes", "unchecked"})
  @Bean
  public ConfigurableJWTProcessor configurableJWTProcessor() throws MalformedURLException {
    ResourceRetriever resourceRetriever =
        new DefaultResourceRetriever(CONNECTION_TIMEOUT, READ_TIMEOUT);
    // https://cognito-idp.{region}.amazonaws.com/{userPoolId}/.well-known/jwks.json.
    URL jwkSetURL = new URL(jwtConfiguration.getJwkUrl());
    // Creates the JSON Web Key (JWK)
    JWKSource keySource = new RemoteJWKSet(jwkSetURL, resourceRetriever);
    ConfigurableJWTProcessor jwtProcessor = new DefaultJWTProcessor();
    JWSKeySelector keySelector = new JWSVerificationKeySelector(RS256, keySource);
    jwtProcessor.setJWSKeySelector(keySelector);
    return jwtProcessor;
  }

  @Bean
  public AWSCognitoIdentityProvider awsCognitoIdentityProvider() {
    return AWSCognitoIdentityProviderClientBuilder.standard()
        .withRegion(Regions.EU_CENTRAL_1)
        .withCredentials(getCredentialsProvider())
        .build();
  }

  @Bean
  public AWSCredentialsProvider getCredentialsProvider() {
    return new ClasspathPropertiesFileCredentialsProvider();
  }
}

我认为这个问题也可能有所帮助。

 类似资料:
  • 本文向大家介绍如何在TestNG中执行时忽略特定的测试方法?,包括了如何在TestNG中执行时忽略特定的测试方法?的使用技巧和注意事项,需要的朋友参考一下 为了从TestNG中执行中忽略特定的测试方法,请使用启用的helper属性。必须将此属性设置为false才能从执行中忽略测试方法。 示例 Java类文件。 在执行过程中,该方法将被忽略。

  • 我希望获得关于如何为Rest API创建集成测试的不同观点。

  • 有时,我们编写的代码并没有准备就绪,并且测试用例要测试该方法/代码是否失败(或成功)。 在本示例中,注释有助于禁用此测试用例。 如果使用注释在测试方法上,则会绕过这个未准备好测试的测试用例。 在本教程中,我们将演示如何使用来忽略测试方法。 创建一个Maven项目,其结构如下所示 - pom.xml 依懒包配置 - 创建一个测试类:TestIgnore.java,其代码如下所示 - 运行上面代码,得

  • 在我的Eclipse项目(Eclipse Luna)中,我有一些JUnit测试用例,我不想在完全回归测试中运行。例如,因为它们需要用户在场以验证结果(例如,如果声音正确播放),或者因为它们只在特定系统上正确运行。这些测试大多是在对被测试类进行更改时手动使用的。我已经使用来忽略这些测试。 当我从Eclipse运行一个包含忽略测试的类(运行为->Junit测试)时,它将在测试列表中显示忽略的测试。

  • 有时,在运行测试用例时,我们的代码并没有完全准备就绪。 结果,测试用例失败。 @Ignore注释在这种情况下@Ignore帮助。 使用@Ignore注释的测试方法将不会被执行。 如果测试类使用@Ignore注释,则不会执行任何测试方法。 现在让我们看看@Ignore在行动。 创建一个类 (Create a Class) 在C:\“JUNIT_WORKSPACE中创建一个要测试的java类,比如Me

  • 使用ESLint是否可以忽略整个目录的一个特定规则? 在我的例子中,我想忽略为一个名为的目录

  • 我有一个spring集成应用程序,它处理数据库中的不同交易类型,我将其转换、过滤并路由到相应的tradeEventChannel 新建行ID- 对于一种特定的交易事件类型(repoTradeChannel),有两种可能的情况: 用户交易开放式回购交易,这转化为一个回购(开放消息)

  • 问题内容: 我想要对Maven项目进行完全自动化的集成测试。集成测试要求在运行之前启动外部(依赖于平台)程序。理想情况下,在单元测试完成后将终止外部程序,但这不是必需的。 有Maven插件可以完成此操作吗?还有其他想法吗? 问题答案: 您可以使用antrun插件。在内部,您将使用ant的 exec apply 任务。 这样的事情。 蚂蚁当然可以通过 条件任务 来支持特定的命令。