View Javadoc
1   /*
2    * SPDX-FileCopyrightText: Copyright (c) 2011-2026 Yegor Bugayenko
3    * SPDX-License-Identifier: MIT
4    */
5   package com.qulice.pmd.rules;
6   
7   import net.sourceforge.pmd.lang.java.ast.ASTBlock;
8   import net.sourceforge.pmd.lang.java.ast.ASTMethodCall;
9   import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
10  import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule;
11  import net.sourceforge.pmd.lang.java.rule.internal.TestFrameworksUtil;
12  
13  /**
14   * Rule to check that JUnit/TestNG test methods do not contain more than
15   * one assertion. Unlike the PMD built-in
16   * {@code UnitTestContainsTooManyAsserts} rule, this implementation does
17   * not count calls to {@code assertThrows} as assertions, because a
18   * common idiom wraps {@code assertThrows(...).getMessage()} inside an
19   * {@code assertThat} to verify the thrown exception's message in a
20   * single logical check.
21   * @since 0.26.0
22   */
23  public final class UnitTestContainsTooManyAssertsRule
24      extends AbstractJavaRulechainRule {
25  
26      public UnitTestContainsTooManyAssertsRule() {
27          super(ASTMethodDeclaration.class);
28      }
29  
30      @Override
31      public Object visit(final ASTMethodDeclaration method, final Object data) {
32          final ASTBlock body = method.getBody();
33          if (body != null
34              && TestFrameworksUtil.isTestMethod(method)
35              && body.descendants(ASTMethodCall.class)
36                  .filter(UnitTestContainsTooManyAssertsRule::isCountedAssert)
37                  .count() > 1) {
38              this.asCtx(data).addViolation(method);
39          }
40          return data;
41      }
42  
43      private static boolean isCountedAssert(final ASTMethodCall call) {
44          return TestFrameworksUtil.isProbableAssertCall(call)
45              && !"assertThrows".equals(call.getMethodName());
46      }
47  }