Debugger does not stop on breakpoint when using testNG and Surefire - spring

I have added testNG to my pom file and created couple of tests.
#WebAppConfiguration
#ContextConfiguration(classes = {PersistenceConfig.class})
#Transactional
#TransactionConfiguration(defaultRollback = true)
public class TrackPersistenceServiceTest extends AbstractTransactionalTestNGSpringContextTests {
private static Logger logger = LoggerFactory.getLogger(TrackPersistenceServiceTest.class);
#Autowired
TrackPersistenceService trackPersistenceService;
// #Test(groups = {"dev"})
public void thatTracksListCanBeUpdated() throws Exception {
EntitiesCreatedEvent event = trackPersistenceService.updateTracksList();
assertTrue( event.getNumOfCreatedEntities()==12 );
}
When I am running the tests with debug mode using:
call mvn -Dmaven.surefire.debug="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=6666 -Xnoagent -Djava.compiler=NONE" test -Dgroups=dev
The surefire starts and is waiting on port 6666.
The problem: is that though I am connecting to it with intellij remote debugger. It executes the tests but the debugger does not stop at the breakpoints.
I am sure the breakpoints are on code that is being executed.
I added to pom:
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.1.1</version>
<scope>test</scope>
</dependency>
Didnt add the surefire plugin to the pom based on this tutorial
Any idea what I am missing?

What I eventually did was to clear the cache.
Though the docs mention File|invalidate cache I could not find and under that menu.
I found it using the find everywhere.
I also update the intellij version.

Related

Can not run Junit in eclipse

I am trying to run spring boot crud example with following code
#SpringBootTest
#RunWith(MockitoJUnitRunner.class)
public class CreateUserServiceTest {
#Mock
private UserRepository userRepository;
#InjectMocks
private CreateUserService createUserService;
#Test
public void whenSaveUser_shouldReturnUser() {
User user = new User();
user.setName("Test Name");
when(userRepository.save(ArgumentMatchers.any(User.class))).thenReturn(user);
User created = createUserService.createNewUser(user);
assertThat(created.getName()).isSameAs(user.getName());
verify(userRepository).save(user);
}
}
But after run it gives bellow error.
"NO test found with test runner 'junit5'"
anyone please help me.
Please check the error message from this file.
Edit: I found the root cause.
JUnit 5 uses annotations from a different package than JUnit 4. When you start a test, Eclipse automatically creates a launch configuration for JUnit 5, but if your annotations are not in the new package, Eclipse would not find the tests and will display the error message.
New annotations:
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
// ... other imports from org.junit.jupiter.api
Old annotations:
import org.junit.Test;
// ... imports without "jupiter" in their name
You need to add the following dependencies in a Maven project in order to use JUnit 5:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<scope>test</scope>
</dependency>
Workaround: Use JUnit 4.
You need to select JUnit 4 in your launch configuration. Otherwise this error is shown.
From the main menu select Run -> Run configurations, then select your JUnit test configuration from the navigation bar on the left hand side.

Spring Boot 2.3.1, JUnit 5, Maven 3.6.3 - Maven lifecycle "test" does not run test suite

pom.xml:
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-runner</artifactId>
<version>1.7.0-M1</version>
<scope>test</scope>
</dependency>
...
In <build> only is used:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
Not in use in <build> are the plugins maven-surefire-plugin and maven-compiler-plugin
There are a few test classes (MyTest1Test, MyTest2Test, etc.), testing REST controllers. Some test methods are tagged with "myTag", to be included in a test suite, like:
#SpringBootTest
#AutoConfigureMockMvc
public class MyTest1Test {
...
#Test
#WithMockUser
public void test1() {...}
#Test
#WithMockUser
#Tag("myTag")
public void test2() {...}
...
}
Also there is a test suite, defined like:
#RunWith(JUnitPlatform.class)
#SelectClasses({MyTest1Test.class, MyTest3Test.class})
#IncludeTags({"myTag"})
public class MyTestSuiteTest {
...
}
When I select Maven > test, all test classes are run, only the test suite is not run. Why not? What kind of configuration has to be done?
When I run the test suite itself by right-click > Run 'MyTestSuiteTest' within the test class, it is run correctly.
Trying replacing #RunWith(JUnitPlatform.class with #ExtendWith(SpringExtension.class) doesn't solve it. Maven > "test" doesn't run the test suite, and worth, trying to run the test suite with IDE (right-click on the class > Run 'MyTestSuiteTest") shows and error:
org.junit.runners.model.InvalidTestClassError: Invalid test class '...MyTestSuiteTest':
1. No runnable methods
at org.junit.runners.ParentRunner.validate(ParentRunner.java:525)
at org.junit.runners.ParentRunner.<init>(ParentRunner.java:102)
at org.junit.runners.BlockJUnit4ClassRunner.<init>(BlockJUnit4ClassRunner.java:84)
at org.junit.runners.JUnit4.<init>(JUnit4.java:23)
at org.junit.internal.builders.JUnit4Builder.runnerForClass(JUnit4Builder.java:10)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:70)
at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:37)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:70)
at org.junit.internal.requests.ClassRequest.createRunner(ClassRequest.java:28)
at org.junit.internal.requests.MemoizingRequest.getRunner(MemoizingRequest.java:19)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:49)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)
The IDE tries to run the test suite with JUnit 4, but why? Because of #SelectClasses, #IncludeTags? I have to include the dependency
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-runner</artifactId>
<version>1.7.0-M1</version>
<scope>test</scope>
</dependency>
to be able to use #SelectClasses and #IncludeTags, but also I excluded the vintage engine. Btw, do I have to remove the exclusion of vintage engine, if running a test suite with #RunWith?
Observation:
Including vintage engine:
Using #RunWith, Maven > "test", shows the following in the console output:
org.junit.vintage.engine.discovery.DefensiveAllDefaultPossibilitiesBuilder$DefensiveAnnotatedBuilder buildRunner
WARNING: Ignoring test class using JUnitPlatform runner: ....MyTestSuiteTest
Running the test suite directly with right-click > Run 'MyTestSuiteTest" via IDE shows an additional entry in the unit test view:
MyTestSuiteTest
JUnit Jupiter
MyTest1Test
test2
MyTest3Test
test1
JUnit Vintage
<no name>
Although there are just two annotated methods to run with the test suite (one from MyTest1Test class, and one from MyTest3Test class), it says 3 test were run successfully. JUnit Vintage didn't show up before when vintage engine was exluded.
Using #ExtendWith with vintage engine included:
Maven > "test" doesn't run the test suite, no warning or similar in the console output. "right-click > Run 'MyTestSuiteTest" gives the reported error.
Excluding vintage engine:
#RunWith behaves as described initially in the question.
#ExtendWith Maven > "test" doesn't run the test suite, no warning or similar in the console output. "right-click > Run 'MyTestSuiteTest" gives the reported error.

Glue code is not loaded when running with cucumber-spring back-end from jar file

I have been trying to get spring-based cucumber tests to run using a combination of Junit(4.12), Cucumber-Java(4.1.1), Cucumber-Spring(4.1.1) and Cucumber-Junit(4.1.1).
I have no issues loading glue code when running the tests from inside the IDE (IntelliJ 2018.3.4) but it seems that for some reason when I try running from the a compiled jar file (which is a requirement in this case) cucumber doesn't find the step definitions.
I've already tried multiple glue code formats such as:
"classpath:com.a.b.c.stepdefs"
"com.a.b.c.stepdefs"
"classpath:com/a/b/c/stepdefs"
I've also tried providing relative paths from the runner class up to the step definitions class (nested just one level below)
"stepdefs"
Also gave a try running using both JUnit and the cucumber.cli.Main and attempted to use different style of step definitions (both cucumber expression - which the missing step snippets are pointing me to - and regex)
I am using the spring-boot-maven-plugin so I am aware that that generally changes the jar structure
All of the above variations fully work when running from the IDE, but not from the jar file
Main Class:
#SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
#ComponentScan(basePackages = {"com.a.b.test.core.data",
"com.a.b.c",
"com.a.b.c.stepdefs"}
)
public class CucumberApplication {
public static void main(String[] args) throws IOException, InterruptedException {
SpringApplication.run(CucumberApplication.class, args);
Result result = JUnitCore.runClasses(RunnerCentral.class);
System.exit(result.wasSuccessful() ? 0 : 1);
}
}
Runner Class:
package com.a.b.c;
#RunWith(Cucumber.class)
#CucumberOptions(features = "classpath:BOOT-INF/classes/features",
glue = "classpath:com/a/b/c/stepdefs",
plugin = "json:target/cucumber-html-reports/cucumber.json")
public class RunnerCentral {
}
POM config of spring-boot-maven-plugin:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.1.0.RELEASE</version>
<configuration>
<fork>true</fork>
<mainClass>${start-class}</mainClass>
<requiresUnpack>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-spring</artifactId>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit</artifactId>
</dependency>
</requiresUnpack>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
I am expecting the behavior to be consistent between running from IDE and running from a packaged source although I may be missing something
Another thing I want to mention is that when swapping the backend with cucumber-picocontainer everything seems to work (spring is a requirement so a swap isn't possible)
This is the kind of issue that can have you launching your hot coffee at the nearest colleague.
Have you seen this post about using a custom ResourceLoader https://github.com/cucumber/cucumber-jvm/issues/1320
I think you'd have to copy and paste the Cucumber.java class, providing the resource loader to the runtime from the Application Context, and change your RunnerCentral class to RunWith the new class.
FWIW in my case, I placed the raw project in a docker container, that on startup ran ./mvnw test which is the Maven Wrapper supplied in Spring Boot projects. You can do ./mvnw test -s /path/to/maven/settings.xml if using a corporate repository, and if your container host can't access the corporate repository, run the image first on the Jenkins box (or wherever the image is being built) which will cause the dependency jars to be downloaded inside, then commit the docker image, and push that image out.
That way, the container can run the cucumber test phase using the local .m2 directory inside it, with the dependencies it needs already there.

Run nested JUnit 5 tests with Maven Surefire

I'm trying to use JUnit 5 in my side project as a trial before migrating my main project. I'd like to use #Nested tests to make my test classes cleaner.
Everything is fine when I ran my test suite as a whole. However, as soon as I try running just a single test, #Nested ones are not executed.
mvn -Dtest=com.mycompany.test.MyTest surefire:test
Is there any way of getting it to run the selected class and all #Nested ones?
Using JUnit 5.1.0, JUnit platform 1.1.0
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<dependencies>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-surefire-provider</artifactId>
<version>${org.junit.platform.version}</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${org.junit.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
Test class:
public class MyTest {
#Test
public void thisTestExecutes() { }
#Nested
public class NestedTests {
#Test
public void thisTestDoesnt() { }
}
}
To run all nested classes you just need to add an "*" at end of class name. Something like:
mvn -Dtest=com.mycompany.test.MyTest\* surefire:test
Facing with same issue, then realized my parent test class name and .java file name are different. I changed my test class name to my .java file name with right click > Refactor > Rename (for possible reference issue). Lastly run my test with following command:
mvn -Dtest=com.mycompany.test.MyTest*
By the way I'm using maven-surefire-plugin 2.22.2 version.
Whole problem is that nested tests are classes compiled the same way as the anonymous classes with a name containing $. The Surefire and Failsafe excludes these by the default pattern
**/*$*
If you use lambda then these exclusions become more and more important.
This should work as well:
mvn test -Dexcludes=nonetest

error: cannot access BlockJUnit4ClassRunner

While i run the mvn install I'm able to find this above error .
This is my POM.xml i have configured JUnit.
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.4</version>
<scope>test</scope>
</dependency>
This is the service Test class
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration
public class ServiceTestCase {
protected static final Logger LOG = Logger.getLogger(ServiceTestCase.class);
#Configuration
static class AccountServiceTestContextConfiguration {
....
....
....
}
While compiling the above error I am getting.
this Test class I have created in src/test/java
can any one please suggest. How to resolve this ?
When I remove the I am getting error as #Test is not recognise.
Ok, the solution might be quite simple: Update to JUnit 4.5 (or higher).
The javadoc of the BlockJUnit4Runner (which is the Superclass of the SpringJUnit4ClassRunner you are using) states:
#since 4.5
...but as you only use <version>4.4</version>, that's probably the whole problem. Just checked it and the class does simply not exist in JUnit 4.4, so you'll have to upgrade your JUnit version to fix that problem.

Resources