Skip to content

[java] JUnitTestsShouldIncludeAssert false positive with inherited @Rule field #1422

@blerner

Description

@blerner

Affects PMD Version: 6.9.0

Rule: JUnitTestsShouldIncludeAssertRule

Description: Thanks to bug #631, this rule properly looks for @Rule ExceptedException fields, and correctly does not complain about tests that use them. However, it only checks for such rules in the current class. One scenario that's come up in my students' code is writing an abstract test class with a bunch of concrete tests and an abstract factory method, and then several concrete test classes that instantiate the factory with one of several implementations. Additionally, they write some concrete tests in the concrete classes. Now, the @Rule isn't a declared field in the same class as the @Tests that use it, so this rule incorrectly fires again.

I think the solution is extending here to walk up the inheritance tree, so far as it's known (and here, it should be known), and check for inherited @Rule fields...

Code Sample demonstrating the issue:

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

abstract class Shape {
  double size;

  Shape(double size) { 
    if (size < 0) {
      throw new IllegalArgumentException("negative size");
    }
    this.size = size; 
  }

  public abstract double area();
}

class Square extends Shape {
  Square(double size) {
    super(size);
  }
  
  public double area() {
    return size * size;
  }
}

class Weird extends Shape {
  Weird(double size) {
    super(size);
  }
  
  public double area() {
    throw new RuntimeException("just 'cause");
  }
}

public abstract class ShapeTester {
  protected abstract Shape factory(double size);

  @Rule
  public ExpectedException e = ExpectedException.none();

  @Test 
  public void notAProblem() {
    e.expect(IllegalArgumentException.class);
    factory(-5);
  }

  public static final class SquareTester extends ShapeTester {
    protected Shape factory(double size) {
      return new Square(size);
    }
  }

  public static final class WeirdTester extends ShapeTester {
    protected Shape factory(double size) {
      return new Weird(size);
    }

    @Test
    public void thisOneTriggersRule() {
      e.expect(RuntimeException.class);
      e.expectMessage("just 'cause");
      factory(42).area();
    }
  }
}

Running PMD through: programmatically

Metadata

Metadata

Assignees

No one assigned

    Labels

    a:false-positivePMD flags a piece of code that is not problematic

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions