How I can resolve this problem (Class<SpringJUnit4ClassRunner> cannot be resolved to a type)? - spring

I realized a simple projetc using spring and maven, my project contains an interface and 3 classes and the pom.xml file
Interface : CompactDisc.java
3 classes :
SgtPeppers.java that implements the CompactDisc interface
CDPlayersConfig.java is an empty class and contains the annotations of automatic scan
CDPlayersTest.java is a test class to test if the spring container works.
My problem is with #RunWith(SpringJUnit4ClassRunner.class) and #ContextConfiguration(classes=CDPlayersConfig.class), Eclipse suggests this proposition for the first annotation Class cannot be resolved to a type and it doesn't understand the second annotation.
You find here the code :
CompactDisc.java
package soundsystem;
public interface CompactDisc {
void play();
}
SgtPeppers.java
package soundsystem;
import org.springframework.stereotype.Component;
#Component
public class SgtPeppers implements CompactDisc{
private String title = "Sgt. Pepper's Lonely Hearts Club Band";
private String artist = "The Beatles";
public void play() {
System.out.println("Playing " + title + "by"+ artist);
}
}
CDPlayersConfig.java
package soundsystem;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
#Configuration
#ComponentScan
public class CDPlayersConfig {
}
CDPlayerTest.java
package soundsystem;
import static org.junit.Assert.assertNotNull;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.jta.SpringJtaSynchronizationAdapter;
#RunWith(SpringJUnit4ClassRunner.class)//Here is my problem
#ContextConfiguration(classes=CDPlayersConfig.class)//Here is my problem
public class CDPlayerTest {
#Autowired
private CompactDisc cd;
#Test
public void cdShouldNotBeNull() {
assertNotNull(cd);
}
}
Dependencies im the pom file
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.0.5.RELEASE</version>
<scope>test</scope>
</dependency>

In Eclipse
Right Click on your Project
Select Maven
Select Update Project
Tick
Update project config from pom.xml
Refresh workspace
Clean projects
After doing that the required libraries should be available to Eclipse and you should be able to import the classes as required.

I can't see
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.ContextConfiguration;
in your import section. Also, maybe you should use SpringRunner.class instead of SpringJUnit4ClassRunner.class

Control+click on the class. Eclipse will open the file. Copy the package name. Create a new import statement and paste the package name + the class name. Problem solved.
If Eclipse does not open the file when you control+click, you don't have it on your class path or imported correctly.

You are missing the imports (import org.springframework...) for SpringJUnit4ClassRunner and ContextConfiguration. That's why they are not recognized.

You have to add dependency:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.9.RELEASE</version>
</dependency>
And then
import org.springframework.test.context.ContextConfiguration;

It's working in my Gradle project after complete some steps.
1st: Add dependency in build.gradle file ->
testImplementation 'junit:junit:4.13.2'
implementation 'org.springframework:spring-test:4.0.0.RELEASE'
2nd: Clean Gradle project using IDE or using command prompt -> Open command prompt -> Go to project location c:\gradle_projects\test_gradle>gradlew clean build -> Enter
3rd: Refresh Gradle project -> Open command prompt -> Go to project location c:\gradle_projects\test_gradle>gradlew --refresh-dependencies -> Enter
4th: Go to IDE -> right-click on project name -> Gradle -> Refresh Gradle Project
-> finally download jar files and import class

Related

Spring Data JDBC + Querydsl: error "JdbcRepositoryFactory does not support Querydsl"

I want to use Spring Data JDBC with QueryDSL support. According to Spring documentation (https://docs.spring.io/spring-data/jdbc/docs/current/reference/html/#core.extensions.querydsl) it is supported, but I couldn't make it working.
I use MariaDB as database and my version of SpringBoot is 2.6.0.
My dependencies in pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-sql-spring</artifactId>
</dependency>
Configuration:
#Configuration
#EnableJdbcRepositories
#EnableTransactionManagement
public class DBConfig {
}
My entity class:
package com.test.model.metadata;
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Table;
#Table
public class Action {
#Id
private long id;
private String name;
...
}
My repository class:
package com.test.repository;
import java.util.List;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Repository;
import com.test.model.Action;
import com.querydsl.core.types.Predicate;
#Repository
public interface ActionRepository extends PagingAndSortingRepository<Action, Long>, QuerydslPredicateExecutor<Action> {
#Override
List<Action> findAll(Predicate predicate);
}
QueryDSL predicate usage:
QAction action = QAction.action;
Predicate predicate = action.name.like("%Accept%");
List<Action> actions = actionRepository.findAll(predicate);
Q-classes are generated properly by preprocessor, compilation suceeds but during application startup I am getting error:
org.springframework.data.repository.core.support.UnsupportedFragmentException: Repository com.atende.db.metadata.jdbcrepository.ActionRepository implements org.springframework.data.querydsl.QuerydslPredicateExecutor but JdbcRepositoryFactory does not support Querydsl!
What yet could be missing in my solution?
When I am using QueryDSL directly with JdbcTemplate it works:
QAction action = QAction.action;
SQLTemplates dialect = new MySQLTemplates();
Connection connection = DataSourceUtils.getConnection(jdbcTemplate.getDataSource());
SQLQuery<String> query = new SQLQuery<>(connection, dialect);
List<Tuple> actions = query.select(action.id, action.name)
.from(action)
.where(action.name.like("%Action%"))
.fetch();
I also tried to use infobip querydsl library (https://github.com/infobip/infobip-spring-data-querydsl) but got the same error.
This is a misinterpretation of the documentation (not your fault, it is structured in an unfortunate way).
You are looking at the preface which describes the general way to work with Spring Data modules.
This does not indicate that the module at hand (JDBC in this case) supports all the features mentioned.
Spring Data JDBC does not provide Querydsl support.
That means that the #EnableJdbcRepositories which activates spring-data-jdbc repository implementation does not provide Querydsl support.
If you have infobip-spring-data-jdbc-querydsl-boot-starter on classpath and remove #EnableJdbcRepositories it should work.
QuerydslJdbcPredicateExecutor is the fragment implementation.

Spring Cucumber ActiveProfiles annotation not working with CucumberContext

I'm working on a project where we have a component which consists:
core
connector to external system 1
connector to external system 2
The connectors are mutually exlusive (if connector1 is active, connector2 is always inactive and vice versa). The core and a single connector are autowired on startup of the ApplicationContext. Which connector is instantiated is based on a value in the spring application properties.
We're writing integration tests using spring-cucumber (v6.2.2). For each external system, I want to run a set of cucumber tests. I've created 2 testsets using annotations on the cucumber scenario's which allows me to seperate the tests for connector1 and connector2.
The problem I'm having is that I need both testsets to run with a different spring profile, so I can use a different configuration. I can't find how to do this.
Current implementation (with a single profile):
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.3.4.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<version>6.2.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit</artifactId>
<version>6.2.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-spring</artifactId>
<version>6.2.2</version>
<scope>test</scope>
</dependency>
CucumberConnector1IT.java
package omitted.for.company.rules;
import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
import org.junit.runner.RunWith;
#RunWith(Cucumber.class)
#CucumberOptions(
features = { "classpath:feature/" },
glue = { "omitted.for.company.rules.cucumber.step" },
plugin = { "pretty", "json:target/cucumber-report/cucumber.json",
"html:target/cucumber-report/cucumber.html" },
tags = "#Connector1 and not #ignore" // tags make sure only applicable tests are run
)
public class CucumberConnector1IT {
}
CucumberConnector2IT.java
package omitted.for.company.rules;
import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
import org.junit.runner.RunWith;
#RunWith(Cucumber.class)
#CucumberOptions(
features = { "classpath:feature/" },
glue = { "omitted.for.company.rules.cucumber.step" },
plugin = { "pretty", "json:target/cucumber-report/cucumber.json",
"html:target/cucumber-report/cucumber.html" },
tags = "#Connector2 and not #ignore" // tags make sure only applicable tests are run
)
public class CucumberConnector2IT {
}
StepInitializer.java
package omitted.for.company.rules.steps;
import io.cucumber.java.Before;
import io.cucumber.spring.CucumberContextConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.ActiveProfiles;
#SpringBootTest
#ActiveProfiles("test") // I can only get this to work if the #ActiveProfiles and #CucumberContextConfiguration annotations are on the same class
#CucumberContextConfiguration
public class StepInitializer {
// mock some beans to use in cucumber test
#MockBean
private EventProducer eventProducer;
#MockBean
private RestInterface restInterface;
#Before
public void setup() {
}
}
So far everything works. But what I need now is to put the #ActiveProfiles() annotation on a different class than the #CucumberContextConfiguration. If I can do this then I can annotate the correct step classes with the required profiles.
Problem is that I don't understand the spring annotations well enough to know which ones I can move and which ones I cannot. I found this example of exactly what I'm trying to do (spring-cucumber-profiles repo, notice the location of the #ActiveProfiles annotation here) . Unfortunately, it uses an older version of cucumber-spring (v5.6.0). That version doesn't yet have the #CucumberContextConfiguration annotation and does some magic with the spring context according to the documentation (Release notes of cucumber-spring). I tried to checkout the example repo and upgrade it to v6.2.2 but couldn't get it working with the new version.
If anyone spots what I'm doing wrong in my own examples, or has the possibility to get the example repo working with version 6.2.2 of cucumber-spring that would be much appreciated.
Thanks in advance! :)
I've solved the issue by separating the packages a bit, and creating separate StepInitializer classes for both testsets.
Current setup:
Test runner:
package omitted.for.company.rules;
import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
import org.junit.runner.RunWith;
#RunWith(Cucumber.class)
#CucumberOptions(
features = { "classpath:feature/" },
extraGlue = { "omitted.for.company.rules.cucumber.step.common" }, // used extraGlue instead of glue
plugin = { "pretty", "json:target/cucumber-report/cucumber.json",
"html:target/cucumber-report/cucumber.html" },
tags = "#Connector1 and not #ignore" // tags make sure only applicable tests are run
)
public class CucumberConnector1IT {
}
Context Configuration:
package omitted.for.company.rules.steps;
import io.cucumber.java.Before;
import io.cucumber.spring.CucumberContextConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.ActiveProfiles;
#SpringBootTest
#ActiveProfiles({ "test", "test-connector1" })
#CucumberContextConfiguration
public class Connector1StepInitializer {
// mock some beans to use in cucumber test
#MockBean
private EventProducer eventProducer;
#MockBean
private RestInterface restInterface;
#Autowired
private ApplicationContext applicationContext;
#Autowired
private Environment environment;
#Before
public void setup() {
assertThat(applicationContext).isNotNull();
assertThat(environment.getActiveProfiles()).containsOnly("test","test-connector1");
}
}
Both connectors/test runners have their own runner class and their own ContextConfiguration class.
It's very important that the classes containing the #CucumberContextConfiguration annotation are not in the shared glue package (as provided in the extraGlue property in the #CucumberOptions annotation).
Package structure looks like this:
├───common
│ └───step // Contains shared steps. This path should be in the 'extraGlue' field of the runner classes
├───connector1
│ │ CucumberConnector1IT.java // Runner 1
│ └───step
│ Connector1Steps.java // Specific steps
│ Connector1StepInitializer.java // has #ActiveProfiles and #CucumberContextConfiguration annotations, use to mock beans
└───connector2
│ CucumberConnector1IT.java // Runner 2
└───step
Connector2Steps.java // Specific steps
Connector2StepInitializer.java // has #ActiveProfiles and #CucumberContextConfiguration annotations, use to mock beans
This way I can still use different spring profiles :).

WebDrivermanager is not opening the browser

I am not able to open both IE and Chrome browsers using WebDriverManager dependency when i run as Maven test. I see that no error is thrown in console and test execution is inprogress even after several minutes.
I have a println statement before the opening the browser which gets printed in the console. Can someone please help me on this?where am I going wrong ?
I am using Spring Test Suite 3.3.0(instead of Eclipse), Java 1.8, Chrome Version - 67.0.3396.99, IE version - 11.0.60
Dependency in pom.xml
<dependency>
<groupId>io.github.bonigarcia</groupId>
<artifactId>webdrivermanager</artifactId>
<version>2.2.3</version>
</dependency>
</dependencies>
Java Class code
import io.github.bonigarcia.wdm.WebDriverManager;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.testng.annotations.Test;
public class SampleTest {
WebDriver driver;
#Test(priority = 2)
public void TC01()
{
System.out.println("Inside TC1");
WebDriverManager.iedriver().setup();
driver = new InternetExplorerDriver();
driver.get("https://www.google.com/");
}
#Test(priority = 1)
public void TC02()
{
System.out.println("Inside TC2");
}
}
Console
You can find a running example of Internet Explorer and WebDriverManager here. Moreover, take a look to the required configuration in Internet Explorer according to the Selenium doc.

jBCrypt dependency not working

I am using heroku embedded tomcat for my web application.
In my user registration page, I have function :
private static String hashPwd(String pwd) {
return BCrypt.hashpw(pwd, BCrypt.gensalt());
}
I added this dependency in pom.xml:
<dependency>
<groupId>org.mindrot</groupId>
<artifactId>jbcrypt</artifactId>
<version>0.3m</version>
</dependency>
But when I try to git push my changes, I get an error:
cannot find symbol : variable BCrypt
at my function call. What am I missing?
My import looks like this:
import org.mindrot.*;
I found the problem. Apparently I had to import :
import org.mindrot.jbcrypt.*
instead of
import org.mindrot.*

How to work with selenium-chrome-driver in Maven without ChromeDriver.exe

I add the below dependency and code for Opening Chrome,but browser is not opening.
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-chrome-driver</artifactId>
<version>2.50.0</version>
</dependency>
My code :-
package example;
import org.openqa.selenium.WebDriver;`
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.Test;
public class DepChrome {
#Test
public void testBrowser() {
WebDriver driver = new ChromeDriver();
driver.manage().window().maximize();
}
}
Add below dependency as below:
<dependency>
<groupId>io.github.bonigarcia</groupId>
<artifactId>webdrivermanager</artifactId>
<version>3.0.0</version>
<!-- <scope>test</scope> -->
</dependency>
Source: copy new dependencies version from below URL:
https://mvnrepository.com/artifact/io.github.bonigarcia/webdrivermanager
use below code :
WebDriver driver = null;
WebDriverManager.chromedriver().browserVersion("77.0.3865.40").setup();
ChromeOptions options = new ChromeOptions();
options.addArguments("start-maximized");
options.addArguments("enable-automation");
options.addArguments("--no-sandbox");
options.addArguments("--disable-infobars");
options.addArguments("--disable-dev-shm-usage");
options.addArguments("--disable-browser-side-navigation");
options.addArguments("--disable-gpu");
driver = new ChromeDriver(options);
driver.get("https://www.google.com/");
Basically below line of code did the trick, below code to download a specific version
WebDriverManager.chromedriver().browserVersion("77.0.3865.40").setup();
Required version you can get from below URL:
https://chromedriver.storage.googleapis.com/index.html
you can also use below code instead of above, if you are looking for latest dependencies present on above chromedriver URL
WebDriverManager.chromedriver().setup();
OR (Old Way)
You need to give path of chrome binary as below:
System.setProperty("webdriver.chrome.driver", "C:\\pathto\\my\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.get("http://www.google.com");
Download the binary of chrome from selenium site as below :-
http://chromedriver.storage.googleapis.com/index.html?path=2.21/
Now provide the path of the binary to selenium as :-
System.setProperty("webdriver.chrome.driver", "C:\\pathto\\my\\chromedriver.exe");
There is one more thing to take care. if you are using windows then use backward slash \\ and if you are using mac or linux then use forward slash // for setting up the path.
Hope it will help you :)
There are two ways.
Easiest way is to download chromedriver from the this location
Download chrome web driver
Then create a source folder in your project. (Ex : BrowserDrivers) and add downloaded library into this.
Then set the chrome driver path in the automation script using setProperty command as follow.
System.setProperty("webdriver.chrome.driver", "BrowserDrivers/chromedriver.exe");
But there is another way. This is more suited for maven build.
Add following dependencies in to the POM.xml file.
There are 2 dependencies. One for Chrome Driver. But to use chrome driver dependency you have to add webdrivermanager dependency. It is compulsory dependency for browser driver. So always you have to add both of them.
For more details refer this link Github Webdriver manager link
<dependency>
<groupId>io.github.bonigarcia</groupId>
<artifactId>webdrivermanager</artifactId>
<version>2.2.5</version>
</dependency>
And add chrome driver dependency also.
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-chrome-driver</artifactId>
<version>2.50.0</version>//Your chrome driver version
</dependency>
Then in your automation script use this line instead of System.setProperty command to declare chrome driver.
ChromeDriverManager.getInstance().setup();
UPDATE: the use of ChromeDriverManager is deprecated, use this instead:
import static io.github.bonigarcia.wdm.DriverManagerType.CHROME;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import io.github.bonigarcia.wdm.WebDriverManager;
WebDriverManager.getInstance(CHROME).setup();
Check below code -
package example;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.Test;
import io.github.bonigarcia.wdm.WebDriverManager;
public class DepChrome {
#Test
public void testBrowser() {
WebDriver driver;
WebDriverManager.chromedriver().setup();
driver = new ChromeDriver();
driver.get("https://google.com");
String title = driver.getTitle();
System.out.println(title);
driver.quit();
}
}
With the following two maven dependencies, you do not need to set system properties at all, this should work
<!-- https://mvnrepository.com/artifact/io.github.bonigarcia/webdrivermanager -->
<dependency>
<groupId>io.github.bonigarcia</groupId>
<artifactId>webdrivermanager</artifactId>
<version>${webdriver-manager.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-chrome-driver -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-chrome-driver</artifactId>
<version>${selenium-chrome-driver}</version>
</dependency>
WebDriver driver;
#BeforeSuite
public void setUp(){
WebDriverManager.chromedriver().setup();
driver = new ChromeDriver();
driver.get("http://www.ebay.in");
driver.manage().timeouts().implicitlyWait(5000, TimeUnit.MILLISECONDS);
}
In Maven, with the use of ChromeDriver.exe:
import static io.github.bonigarcia.wdm.DriverManagerType.CHROME;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import io.github.bonigarcia.wdm.WebDriverManager;
import org.testng.annotations.Test;
public class MavenTest {
#Test
public void TestMaven()
{
System.setProperty("webdriver.chrome.driver", "D:\\Sumit_Backup\\Automation\\Workspace\\Maven\\src\\Browser\\chromedriver.exe");
WebDriver driver= new ChromeDriver();
driver.get("http://testng.org/doc/maven.html");
driver.manage().window().maximize();
}
}

Resources