Search code examples
javagradlejunitclasspathvscode-extensions

JUnit Testing on HTTPS-cloned Java project w/ Gradle build on VSCode Apple Silicon


For university, I need to clone project templates onto my machine in order to complete the tasks. Previously on IntelliJ, it would automatically do all the imports and work behind the scenes whenever I just added a file somewhere random in the project and started using JUnit tests. I recently made the switch to VSCode and am finding it much more difficult to use, but its somewhat mandatory.

After cloning the project templates (which have Gradle as a build tool) and adding a class in the 'src' directory to write some JUnit tests, I get a NoClassDefFoundError when trying to run said tests. Here is the project structure looks after I add it. Before, it is the same, just without the two .java files that I added for testing (TestHelper.java and Testing.java):

fileName (can't disclose because of privacy)
- .gradle
- .vscode
 -- settings.json
- bin
- build
- gradle
- src
 -- moduleName (can't disclose because of privacy)
  --- maze (contains all the classes for solving the task)
 -- TestHelper.java
 -- Testing.java
- .gitattributes
- .gitignore
- build.gradle
- gradlew
- gradlew.bat
- settings.gradle

Also, here is the build.gradle file, not as cloned because I added the dependencies block myself and the sourceSets block was structured like this before:

sourceSets {
    main {
        java {
            srcDir 'src'
        }
    }
    test {
        java {
            srcDirs = []
        }
    }

}

So, here is the current build.gradle:

apply plugin: 'java'
sourceCompatibility = 17
version = '1.0.0'
compileJava.options.encoding = 'UTF-8'

repositories {
    mavenCentral()
}

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.3'
}

sourceSets {
    main {
        java {
            srcDir 'src'
        }
    }
    test {
        java {
            srcDir 'src'
        }
    }

}

I have been stuck on the problem for days and tried multiple things:

  1. I tried to see if it was a set-up or extension issue but was able to create a dummy Gradle project locally and run tests there without any problems.

  2. At first VSCode wouldn't even recognize the tests. I then fooled around with the build.gradle file until it would recognize the tests, and that is when I tried running them and got the NoClassDefFoundError on the Testing.java class. I also cleared the Java Language Server workspace multiple times to make VSCode pick up the tests.

  3. I have gone online and gleaned that the error has something to do with the runtime classpath and the compile-time classpath. However, I thought Gradle is supposed to take care of the classpath for you, and don't understand how to amend my classpaths to include the classes I added, if I understood that correctly.

I am quite new to VSCode, Java and programming in general. I'd appreciate any help that I could get.


Solution

  • JUnit 5 is split into a number of different modules. For writing and running tests, the important ones are:

    • junit-jupiter-api - classes, interfaces and annotations for writing tests
    • junit-jupiter-engine - needed to run the tests
    • junit-jupiter-params - additional API for writing parameterised tests

    To write and run tests you need at least both of junit-jupiter-api and junit-jupiter-engine (the latter only at runtime):

    dependencies {
        testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.3'
        testRUntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.3'
    }
    

    Alternatively, there's an aggregate module simply called junit-jupiter that provides all 3 of the dependencies listed above, so the following should also work:

    dependencies {
        testImplementation 'org.junit.jupiter:junit-jupiter:5.9.3'
    }