I was looking for some way to have some #beforeMethod logic executing only for a group of java unit tests (using TestNG ).
I found on TestNG documentation:
onlyForGroups: Only for #BeforeMethod and #AfterMethod. If specified,
then this setup/teardown method will only be invoked if the
corresponding test method belongs to one of the listed groups.
Which seems to be what I'm looking for.
But when I try to use it, it's not implemented in #BeforeMethod and #AfterMethod annotations. I couldn't find find any information on the web about it missing.
Maven dependency :
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.14.2</version>
<scope>test</scope>
</dependency>
Thanks for the help
Upgrade you version, as you see in Changes, it was added after 6.14.3 version
Fixed: GITHUB-549 and GITHUB-780: Introduce onlyForGroups attribute for #BeforeMethod and #AfterMethod (Sergei Tachenov)
Notice the version of TestNG used in the dependency.
<dependencies>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.4.0</version>
<scope>test</scope>
</dependency>
</dependencies>
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
public class TestNgBeforeMethodAnnotation {
#BeforeMethod(onlyForGroups = {"Group1"}, groups = {"Group1"})
public void setupForGroup1()
{
System.out.println("Before Method for Group 1 called");
}
#Test(groups = {"Group1"})
public void testCaseInGroup1()
{
System.out.println("testCaseInGroup1");
}
}
Related
I spent a whole day trying to find why this does not work so I think it might be useful if I share the question and the answer.
The Resilience4j library provides an elegant annotation-based solution from Spring Boot 2. All you need to do is just annotate a method (or a class) with one of the provided annotations, such as #CircuitBreaker, #Retry, #RateLimiter, #Bulkhead, #Thread and the appropriate resilience pattern is automagically added.
I added the expected dependency to the Maven pom.xml:
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-spring-boot2</artifactId>
<version>${resilience4j.version}</version>
</dependency>
Now the compiler is happy, so I can add the annotations:
...
import org.springframework.stereotype.Service;
import io.github.resilience4j.retry.annotation.Retry;
...
#Service
public class MyService {
...
#Retry(name = "get-response")
public MyResponse getResponse(MyRequest request) {
...
}
}
The program compiles, runs, however the annotations are completely ignored.
According to the resilience4j-spring-boot2 documentation:
The module expects that spring-boot-starter-actuator and spring-boot-starter-aop are already provided at runtime.
So the whole trick is to add also the missing dependencies to the Maven pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
I would like to test my controller class. But I couldn't manage to run springBootTest class. My project written in spring boot. We are writing REST API using spring boot.
When I try to excute following test class. I still get following line from terminal.
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.context.SpringBootTest;
import static org.assertj.core.api.Assertions.assertThat;
/*
*
* #A Sabirov Jakhongir
*
*/
#SpringBootTest
#WebMvcTest
public class PrivilegesControllerTest {
#Autowired
private PrivilegesController privilegesController;
#Test
public void add() {
assertThat(privilegesController).isNotNull();
}
}
I put here all needed dependency for testing from my project.
<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>
<!-- https://mvnrepository.com/artifact/org.junit.platform/junit-platform-launcher -->
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<version>1.6.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.3.2</version>
<scope>test</scope>
</dependency>
What might be cause of not working of test Class.
With Junit5 and #SpringBootTest will load the full application, I had faced the same issue before, you can find details about the question here and answer here.
The solution for this is to use your test without #SpringBootTest.
The solution to your test class is as below.
#ExtendWith(MockitoExtension.class)
public class PrivilegesControllerTest {
#InjectMocks
private PrivilegesController privilegesController;
#Test
public void add() {
assertThat(privilegesController).isNotNull();
}
}
You can also use #ExtendWith(SpringExtension.class) instead of #ExtendWith(MockitoExtension.class)
To test spring boot application is creating your controller, use #SpringBootTest annotation, and to test the behavior or responsibility of the controller is better to use #WebMvcTest. No need to annotate both the annotation to one class.
There are two cases to test the controller's responsibility.
With running Server
Without Server
For 1st Case, you can use #SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) to start a server with a random port.
For 2nd Case, use #WebMvcTest for testing the web layer.
All the test cases are written with the following signature:
#Test
public void test_Name() throws Exception {
//your test definition
}
You can also read the Official Documentation of Spring Boot https://spring.io/guides/gs/testing-web/
I am writing test cases for my project using Junit5, when I run a test cases all the test cases passes, but some of them gives me below error in console
WARNING: TestEngine with ID 'junit-jupiter' failed to execute tests
java.lang.NoClassDefFoundError: junit/framework/ComparisonFailure
at org.eclipse.jdt.internal.junit5.runner.JUnit5TestListener.getFailedComparison(JUnit5TestListener.java:133)
at org.eclipse.jdt.internal.junit5.runner.JUnit5TestListener.notifyIfNotSuccessful(JUnit5TestListener.java:89)
at org.eclipse.jdt.internal.junit5.runner.JUnit5TestListener.executionFinished(JUnit5TestListener.java:71)
at org.junit.platform.launcher.core.TestExecutionListenerRegistry$CompositeTestExecutionListener.lambda$executionFinished$3(TestExecutionListenerRegistry.java:77)
at java.util.ArrayList.forEach(Unknown Source)
at org.junit.platform.launcher.core.TestExecutionListenerRegistry.notifyTestExecutionListeners(TestExecutionListenerRegistry.java:51)
at org.junit.platform.launcher.core.TestExecutionListenerRegistry.access$100(TestExecutionListenerRegistry.java:27)
at org.junit.platform.launcher.core.TestExecutionListenerRegistry$CompositeTestExecutionListener.executionFinished(TestExecutionListenerRegistry.java:77)
at org.junit.platform.launcher.core.ExecutionListenerAdapter.executionFinished(ExecutionListenerAdapter.java:56)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.reportCompletion(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:79)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:170)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:154)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:90)
at org.eclipse.jdt.internal.junit5.runner.JUnit5TestReference.run(JUnit5TestReference.java:89)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)
for e.g.
Mockito.verify(exportFile, Mockito.times(1)).exportCsvFile(Mockito.anyList(), Mockito.anyString());
Mockito.verify(exportFile, Mockito.times(2)).exportCsvFile(Mockito.anyList(), Mockito.anyString());
Mockito.verify(exportFile, Mockito.times(3)).exportCsvFile(Mockito.anyList(), Mockito.anyString();
Every time test case passes, but for second and third case I am seeing java.lang.NoClassDefFoundError: junit/framework/ComparisonFailure
Below is how my pom looks like:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<!-- exclude junit 4 -->
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- junit 5 -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
Below is how my test class looks like (provided necessary part of the class).
public class AccountServiceTest {
AccountService AccountService;
#Mock
ExportFile exportFile;
#BeforeEach
public void init() {
MockitoAnnotations.initMocks(this);
accountService = new AccountService(exportFile);
}
#Test
public void testFileExport() {
accountService.process(partner.getName());
Mockito.verify(exportFile).exportCsvFile(Mockito.anyList(), Mockito.anyString());
}
}
If you can upgrade your spring-boot-starter-test to at least 2.2.0.RELEASE it will bring you JUnit 5 (the exclusion is also not necessary if you want run JUnit4 and JUnit5 tests at the same time). Using only spring boot starter dependencies is a good way to handle incompatible version issue between dependencies as spring boot manages that for you.
If you want run a test with JUnit5 and Mockito, your class should look like this (the object you want to test is annotated with #InjectMocks and it's dependency you want mock with #Mock and the class test with #ExtendWith(MockitoExtension.class)) :
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
#ExtendWith(MockitoExtension.class)
public class AccountServiceTest {
#Mock
ExportFile exportFile;
#InjectMocks
AccountService accountService;
#Test
public void testFileExport() {
accountService.process("");
Mockito.verify(exportFile).exportCsvFile(Mockito.anyList(), Mockito.anyString());
}
}
I am using the following spock dependency
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-core</artifactId>
<version>1.0-groovy-2.4</version>
<scope>test</scope>
</dependency>
I wrote this test
class JsonIncludeResolverTest extends Specification {
JsonIncludeResolver uut;
def "test"(){
expect:
true
}
}
the test succeeds
Now I want to use Spring to inject JsonIncludeResolverwithin the specification.
JsonIncludeResolver is annotated with #Component and is injected successfully when running the application. Both tests and component are placed in the same maven module.
I read about spring-spock here: How to inject spring beans into spock test
Therefore I added this dependency version
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-spring</artifactId>
<version>1.1-groovy-2.4</version>
<scope>test</scope>
</dependency>
after adding this dependency running the s
Exception in thread "main" java.lang.NoSuchMethodError: org.spockframework.util.ReflectionUtil.isAnnotationPresentRecursive(Ljava/lang/Class;Ljava/lang/Class;)Z
at org.spockframework.spring.SpringExtension.isSpringSpec(SpringExtension.java:83)
at org.spockframework.spring.SpringExtension.visitSpec(SpringExtension.java:59)
at org.spockframework.runtime.ExtensionRunner.runGlobalExtensions(ExtensionRunner.java:46)
at org.spockframework.runtime.ExtensionRunner.run(ExtensionRunner.java:40)
at org.spockframework.runtime.Sputnik.runExtensionsIfNecessary(Sputnik.java:88)
at org.spockframework.runtime.Sputnik.getDescription(Sputnik.java:55)
at com.intellij.junit4.JUnit4IdeaTestRunner.getDescription(JUnit4IdeaTestRunner.java:78)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:50)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
I then tried to use the proper annotations
#ContextConfiguration
class JsonIncludeResolverTest extends Specification {
#Autowired
JsonIncludeResolver uut;
def "test"(){
expect:
uut != null
}
}
Still the result is the above exception.
The groovy test is under /src/test/groovy which is a working as you could see in the first successful run of the test.
Try upgrading Spock to 1.1 as follows:
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-core</artifactId>
<version>1.1-groovy-2.4</version>
<scope>test</scope>
</dependency>
org.spockframework.util.ReflectionUtil.isAnnotationPresentRecursive() has been introduced since version 1.1 by this commit.
I created a automated test scenario using selenium + cucumber on java, and when I try to execute my test nothing occur. I don't know what I did worng but I think that something happend with my feature, because exist warning on the following messages "No definition found for I try to login on facebook", "No definition found for I put my user "email"", "No definition found for I put my password "pass"" and "No definition found for validate login".
I imported these jars using maven: cucumber-java : 1.2.5/cucumber-junit : 1.2.5/selenium-java : 3.0.1/selenium-firefox-driver : 3.0.1/junit : 4.12
RunTest.java
package com.tdd.facebook;
import org.junit.runner.RunWith;
import cucumber.api.junit.Cucumber;
import cucumber.api.CucumberOptions;
#RunWith(Cucumber.class)
#CucumberOptions(
format = {"pretty", "html:target/cucumber"},
features = {"src/test/resources"}
)
public class RunTest {
public RunTest() {
// TODO Auto-generated constructor stub
}
}
LoginSteps.java
package com.tdd.facebook;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import cucumber.api.PendingException;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;
public class LoginSteps {
WebDriver driver = null;
#Given("^I try to login on facebook$")
public void i_try_to_login_on_facebook() throws Throwable {
System.setProperty("webdriver.gecko.driver", "C:\\Caio\\Selenium\\geckodriver.exe");
WebDriver driver = new FirefoxDriver();
driver.get("https://www.facebook.com/");
throw new PendingException();
}
#When("^I put my user \"([^\"]*)\"$")
public void i_put_my_user(String email) {
driver.findElement(By.id(email)).click();
driver.findElement(By.id(email)).sendKeys("UserTest");
}
#When("^I put my password \"([^\"]*)\"$")
public void i_put_my_password(String pass){
driver.findElement(By.id(pass)).click();
driver.findElement(By.id(pass)).sendKeys("Test");
}
#Then("^validate login$")
public void validate_login() throws Throwable {
System.out.println("Login OK");
}
public LoginSteps() {
// TODO Auto-generated constructor stub
}
}
Login.feature
Feature: Login on facebook
Scenario: Check if the login is successful
Given I try to login on facebook
When I put my user "email"
When I put my password "pass"
Then validate login
pow.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.tdd</groupId>
<artifactId>facebook</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>facebook</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-java</artifactId>
<version>1.2.5</version>
</dependency>
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-junit</artifactId>
<version>1.2.5</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-firefox-driver</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
</project>
You need to add glue option to cucumberoptions with the path to the step definition classes. Use glue="com.tdd.facebook". I am not sure about this but you might want to remove the constructor in the runner RunTest.
In the LoginStps class - i_try_to_login_on_facebook() method, you are declaring another driver variable and initializing it. Thus the driver field of the class will remain null. Remove this. Also in the same method you are throwing a k. As you have implemented the step you do not need it anymore.
Also do check if all the jars are imported in the pom. I think you are missing some jars. Check the cucumber java page.