javaeclipseinterfaceassertjjunit3

Can't use assertThat in test case - "The method assertThat(Point) is undefined for the type CleverBrainTest"


I'm taking an entry-level Java course and have run into an issue that is preventing me from submitting an assignment.

I have to use assertThat in my test cases to satisfy the automatic grader's requirement that I write unit tests. The issue is that I am unable to use the method without receiving this error: "The method assertThat(Point) is undefined for the type CleverBrainTest"

In Eclipse, the error shows up as a red lightbulb to the left of every line where I try to use assertThat. The error also shows up in the testing result when I attempt to run the test.

Eclipse suggests that I use assertTrue instead, and this works. However, the automatic grading system for my class rejects it. It will only accept assertThat.

Additional context:

I'm including my test case titled CleverBrainTest in the post. Please bear with me as I am very new to Java. Any guidance is greatly appreciated, and I can supply more information if needed. I'm very interested in learning why this is happening so I can address similar issues in the future. Below is the code, I'll also include the trace for the error.

// -------------------------------------------------------------------------
import student.*;
import student.tetris.*;
import static org.assertj.core.api.Assertions.*;

/**
 *  Tests to measure performance of CleverBrain
 * 
 *  @author My Name
 *  @version Today's Date
 */
public class CleverBrainTest
    extends TestCase
{
    //~ Fields ................................................................
    
    
    //~ Constructors ..........................................................

    //~Public  Methods ........................................................    
    /**
     * Tests brain's ability to place sticks in deep holes
     */
    public void testStickInDeepHole()
    {
        Board deepHole = new Board(10, 24,
            "######### ",
            "######### ",
            "######### ",
            "######### "
            );
        Brain myBrain = new CleverBrain();
        Piece stick = Piece.getPiece(Piece.STICK, 0);
        Move best = myBrain.bestMove(deepHole, stick, 20);   

        // Now call the brain
        best = myBrain.bestMove(deepHole, stick, 20);

        // Expect the piece will go to the bottom right hole
        this.assertThat(best.getLocation()).isEqualTo(new Point(10, 0));
        // Expect the piece is rotated counter-clockwise 0 times
        this.assertThat(best.getPiece()).isEqualTo(Piece.SQUARE, 0); // make sure it's correct
    }
    
    
    /**
     * Tests Brain's ability to choose a reasonable target
     */
    public void testSetTarget()
    {
        Board squareHole = new Board(10, 24,
            "          ",
            "#####  ###",
            "#####  ###",
            "##########"
            );
        Brain myBrain = new CleverBrain();
        Piece square = Piece.getPiece(Piece.SQUARE, 0);
        Move best = myBrain.bestMove(squareHole, square, 20);

        // Now call the brain
        best = myBrain.bestMove(squareHole, square, 20);
        
        // Expect the lower left destination is where the hole is
        System.out.println(best.getLocation());
        this.assertThat(best.getLocation()).isEqualTo(new Point(5, 1));
    }
}

The trace for the error

java.lang.Error: Unresolved compilation problem: 
    The method assertThat(Point) is undefined for the type CleverBrainTest

    at CleverBrainTest.testSetTarget(CleverBrainTest.java:66)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at junit.framework.TestCase.runTest(TestCase.java:176)
    at junit.framework.TestCase.runBare(TestCase.java:141)
    at junit.framework.TestResult$1.protect(TestResult.java:122)
    at junit.framework.TestResult.runProtected(TestResult.java:142)
    at junit.framework.TestResult.run(TestResult.java:125)
    at junit.framework.TestCase.run(TestCase.java:129)
    at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:128)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:40)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:529)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:756)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:452)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)


Things I Have Tried


Solution

  • In Java, this refers the to the instance of the enclosing class which the method was invoked on. For example, if you have the following:

    public class Person {
    
      private final String name;
    
      public Person(String name) {
        // 'this' is differentiating between the 'name' *field* 
        // and the 'name' *parameter*
        this.name = name;
      }
    
      public void speak() {
        // Note the only 'name' in scope here is the field, so 
        // technically 'this` can be omitted (and typically is)
        System.out.println("Hello, from " + this.name + "!");
      }
    
      public static void main(String[] args) {
        Person p1 = new Person("John");
        Person p2 = new Person("Jane");
    
        p1.speak();
        p2.speak();
      }
    }
    

    You would see the following output:

    Hello, from John!
    Hello, from Jane!
    

    Because:

    Note that this cannot be used in static contexts (e.g., the main method above) because there is no "current instance" in static contexts.

    By using:

    this.assertThat(best.getLocation()).isEqualTo(new Point(10, 0));
    

    You are explicitly telling Java to invoke an assertThat method on this, where this is an instance of CleverBrainTest in this context. But that class does not have an assertThat method, thus the code fails to compile. The assertThat method comes from AssertJ's Assertions class. It is also a static method, meaning you do not need an instance of Assertions to call it.

    One way to fix this is to import org.assertj.core.api.Assertions and then use:

    Assertions.assertThat(best.getLocation()).isEqualTo(new Point(10, 0));
    

    However, you already have the following import:

    import static org.assertj.core.api.Assertions.*;
    

    That is a static import. Static imports let you reference static members (e.g., methods, enum constants, etc.) without having to prefix them with the class name. That import is also a star import, which means every static member of Assertions is being imported. All that means you can simply do:

    assertThat(best.getLocation()).isEqualTo(new Point(10, 0));
    

    Without the Assertions prefix and it will still work. Though note if CleverBrainTest did have an assertThat method then that method would take precedence over the statically imported assertThat method, so in that case you would have to prefix the method call with Assertions in order to call the correct one.


    Eclipse suggests that I use assertTrue instead, and this works.

    There is no assertTrue method in the code you provided, so I can only assume it comes from the TestCase superclass (which I believe is a JUnit 3 class?).