Spring Boot GUI Testing Selenium WebDriver - angularjs

I developped a Spring Boot / Angular JS app. Now I'm trying to implement some GUI interface tests.
I tryed to use the Selenium ChromeDriver, so I added the Selenium dependency :
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.4.0</version>
</dependency>
And I created my first test :
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = MyMainClass.class)
public class SeleniumTest {
private WebDriver driver;
#Before
public void setup() {
System.setProperty("webdriver.chrome.driver", "my/path/to/chomedriver");
driver = new ChromeDriver();
}
#Test
public void testTest() throws Exception {
driver.get("https://www.google.com/");
}
}
This works fine. But now I want to get my app pages with :
driver.get("http://localhost:8080/");
But I get an "ERR_CONNECTION_REFUSED" in the chrome browser.
I think it's because I need to set up my test to run my web app before to run the test but I don't find how to achieve this ?

In your case service is not started. Try something like this this.
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class SeleniumTest {
#LocalServerPort
private int port;
private WebDriver driver;
#Value("${server.contextPath}")
private String contextPath;
private String base;
#Before
public void setUp() throws Exception {
System.setProperty("webdriver.chrome.driver", "my/path/to/chromedriver");
driver = new ChromeDriver();
this.base = "http://localhost:" + port;
}
#Test
public void testTest() throws Exception {
driver.get(base + contextPath);
}
}
UPDATE:
Add the dependency
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

Related

Camel bean component invokes cached instance of #Named / #Dependent bean

In our application we are using Apache Camel with camel-cdi component in JBoss EAP 7.1 environment. After upgrade of Apache Camel to actual version the application started to behave incorrectly in parallel execution.
I have found, that bean component invokes always the same instance. From my understanding, bean with #Dependent scope should be always fresh instance for every CDI lookup.
I have tried endpoint parameter cache=false, which should be default, but the behavior stays the same. Also tried to specify #Dependent, which should be default too.
Attaching MCVE, which fails on Apache Camel 2.20.0 and newer. Works well with 2.19.5 and older. Full reproducible project on Github.
#ApplicationScoped
#Startup
#ContextName("cdi-context")
public class MainRouteBuilder extends RouteBuilder {
public void configure() throws Exception {
from("timer:test")
.to("bean:someDependentBean?cache=false");
}
}
#Named
//#Dependent //Dependent is default
public class SomeDependentBean implements Processor {
private int numOfInvocations = 0;
private static Logger log = LoggerFactory.getLogger(SomeDependentBean.class);
public void process(Exchange exchange) throws Exception {
log.info("This is: "+toString());
numOfInvocations++;
if (numOfInvocations!=1){
throw new IllegalStateException(numOfInvocations+"!=1");
} else {
log.info("OK");
}
}
}
Is there anything I can do in our application to change this behavior and use actual version of Apache Camel?
EDIT:
Removing tags camel-cdi and jboss-weld. I have created unit test, to simulate this situation without dependencies to camel-cdi and Weld. This test contains assertion to test JndiRegistry#lookup, which returns correct instance. According this test I believe, the issue is in bean component itself. Fails with version >=2.20.0 and passes with <=2.19.5
public class CamelDependentTest extends CamelTestSupport {
private Context context;
private JndiRegistry registry;
#Override
protected RoutesBuilder createRouteBuilder() throws Exception {
return new RouteBuilder() {
#Override
public void configure() throws Exception {
from("direct:in")
.to("bean:something?cache=false");
}
};
}
#Override
protected JndiRegistry createRegistry() throws Exception {
JndiRegistry registry = super.createRegistry();
registry.bind("something", new SomeDependentBean());
this.context = registry.getContext();
this.registry = registry;
return registry;
}
#Test
public void testFreshBeanInContext() throws Exception{
SomeDependentBean originalInstance = registry.lookup("something", SomeDependentBean.class);
template.sendBody("direct:in",null);
context.unbind("something");
context.bind("something", new SomeDependentBean()); //Bind new instance to Context
Assert.assertNotSame(registry.lookup("something"), originalInstance); //Passes, the issue is not in JndiRegistry.
template.sendBody("direct:in",null); //fails, uses cached instance of SameDependentBean
}
}
According CAMEL-12610 is Processor supposed to be singleton scope. This behavior was introduced in version 2.20.0. Do not implement Processor interface, instead annotate invokable method as #Handler.
Replace
#Named
public class SomeDependentBean implements Processor {
public void process(Exchange exchange) throws Exception {
}
}
with
#Named
public class SomeDependentBean {
#Handler
public void process(Exchange exchange) throws Exception {
}
}
If you cannot afford that as me, because it is breaking behavior for our app extensions, I have implemented simple component. This component have no caching and allows to invoke Processor directly from registry.
CdiEndpoint class
public class CdiEndpoint extends ProcessorEndpoint {
private String beanName;
protected CdiEndpoint(String endpointUri, Component component) {
super(endpointUri, component);
}
public void setBeanName(String beanName) {
this.beanName = beanName;
}
#Override
protected void onExchange(Exchange exchange) throws Exception {
Object target = getCamelContext().getRegistry().lookupByName(beanName);
Processor processor = getCamelContext().getTypeConverter().tryConvertTo(Processor.class, target);
if (processor != null){
processor.process(exchange);
} else {
throw new RuntimeException("CDI bean "+beanName+" not found");
}
}
}
CdiComponent class
public class CdiComponent extends DefaultComponent {
#Override
protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception {
CdiEndpoint endpoint = new CdiEndpoint(uri, this);
endpoint.setBeanName(remaining);
return endpoint;
}
}
Usage
public void configure() throws Exception {
getContext().addComponent("cdi", new CdiComponent());
from("direct:in")
.to("cdi:something");
}

How to intercept or aop javax.sql.Datasource.getConnection() using spring aop

I am trying to aspect the javax.sql.Datasource.getConnection() so that I can set clientInfo properties before the connection is used.
I tried spring ConnectionInterceptor with COnnectionPreparer but it did not work.
I tried pointcut with javax.sql.datasource.getConnection() but not working.
now , am trying pointcut with the below but my advise is not executed rather the call just passes through.
pom.xml has
<!-- https://mvnrepository.com/artifact/aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
main class
#SpringBootApplication
#Configuration
#EnableAutoConfiguration
#ComponentScan({ "com.xyz" })
#EnableAspectJAutoProxy
public class MainApplication extends SpringBootServletInitializer {
// spring configuration here
// cxf end point configuration
}
aspect class
#Component
#Aspect
public class ClientIdentifierConnectionPreparer {
#AfterReturning(pointcut="execution(java.sql.Connection org.springframework.jdbc.datasource.ConnectionHandle.getConnection())", returning="conn")
public void prepare(Connection conn) {
System.out.println("prepare connection aspect 1");
}
#Before("execution(java.sql.Connection org.springframework.jdbc.datasource.ConnectionHandle.getConnection())")
public void prepareBefore() {
System.out.println("prepare connection aspect 2");
}
}
can you pls help

Spring Data MongoDB Testing

I wrote a small study-project to play a little bit with mongodb. I was using Spring Data to get Mongo Repository. It was quite easy to create RestController and using MongoRepository through Service (another class) retrieve info from mongodb and render it to the browser.
public interface PersonRepository extends MongoRepository<Person, Integer> {
List<Person> findByName(String name);
#Query("{'name':{$regex:?0}}")
List<Person> findByNameLike(String nameLike);
//the rest of methods
}
Now I decided to test my business logic and created the following class:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {AppConfig.class})
public class TestMongo {
private static final Logger LOG = LoggerFactory.getLogger(TestMongo.class);
#Autowired
private PersonRepository personRepository;
#Before
public void setUp() {
Technology technology1 = new Technology("Java-7");
Technology technology2 = new Technology("Java-8");
Technology technology3 = new Technology("Hibernate");
Technology technology4 = new Technology("MyBatis");
Technology technology5 = new Technology("Spring Data");
Project project1 = new Project(1, "POINT", Arrays.asList(technology1, technology3));
Project project2 = new Project(2, "Forecast", Arrays.asList(technology1, technology4));
Project project3 = new Project(3, "CPM", Arrays.asList(technology2, technology5));
Person person1 = new Person(1, "Alex", 27, Arrays.asList(project1, project3));
Person person2 = new Person(2, "Ivan", 26, Arrays.asList(project2, project3));
Person person3 = new Person(3, "Andrii", 31, Arrays.asList(project1));
personRepository.save(Arrays.asList(person1, person2, person3));
}
#Test
public void count() {
List<Person> all = personRepository.findAll();
LOG.info("There are " + all.size() + " person(s) in database");
assertThat(all.size(), equalTo(3));
}
#Test
public void findByName() {
List<Person> personList = personRepository.findByName("Ivan");
LOG.info("*******Find by name********");
LOG.info("personList {}", personList);
LOG.info("***************************");
assertThat(personList, hasSize(1));
}
//another test methods
#After
public void shutDown() {
personRepository.deleteAll();
}
}
where AppConfig.class looks as:
#Configuration
#EnableMongoRepositories
#ComponentScan
public class AppConfig {
#Bean
public MongoClient mongoClient() {
return new MongoClient("localhost", 27017);
}
#Bean
public MongoTemplate mongoTemplate() {
return new MongoTemplate(mongoClient(),"my-mongo");
}
}
And now my problem: I don't actually want to run some tests on the same database where I store my data. Moreover, I have a crucial method personRepository.deleteAll() after which all the data will just vanish.
I found embedded mongodb as a solution but once I add it to my pom.xml I don't see my installed database anymore.
So, the question is whether it's possible to have both installed and embedded mongodb on the same machine and if not how to test my MongoRepository without modifying prod data.
It looks like I found what I was missing:
<dependency>
<groupId>de.flapdoodle.embed</groupId>
<artifactId>de.flapdoodle.embed.mongo</artifactId>
<version>1.50.5</version>
<scope>test</scope>
</dependency>
Simply adding scope test is launching my embedded mongodb for tests only, while I'm still using installed mongodb for prod.

Camel blueprint testing and cucumber

Is it possible to combine cucumber with CamelBlueprintTestSupport? I have my runner class:
#RunWith(Cucumber.class)
#CucumberOptions(monochrome=true,
format={ "pretty", "html:target/cucumber"},
features = "C:/Users/Developer/workspace_camel/SRV002_PatronInformation/src/test/resources/cucumber/asynchronousErrorHandling.feature")
public class RunFeature_SRV002_PatronInformationTest {
}
and my blueprint test class with the scenarios:
public class SRV002_PatronInformationScenarioTest extends CamelBlueprintTestSupport {
#Override
protected String getBlueprintDescriptor() {
return "/OSGI-INF/blueprint/blueprint.xml";
}
#Given("^client communicates asynchronous via socket$")
public void client_communicates_asynchronous_via_socket() throws Throwable {
System.out.println("test");
}
#When("^client posts message$")
public void an_error_occurs_inside_the_integration() throws Throwable {
String endpoint = "netty4:tcp://localhost:5000?sync=false&textline=true";
template.sendBody(endpoint, "test");
}
#Then("^the integration should not return response to the client$")
public void the_integration_should_not_return_the_error_to_the_client() throws Throwable {
System.out.println("test");
}
}
The problem now is that, when I run this I run into nullpointerexception at template.sendbody because the context, bundle and routes haven't started. For some reason it seems adding #RunWith(Cucumber) prevents the camel routes from starting.
Anyone knows how this can be solved? Thanks
Souciance
Ok so I managed to solve this.
For reference look here:
http://camel.465427.n5.nabble.com/How-to-test-routes-when-using-another-TestRunner-td5772687.html
Thanks to Gregor Lenz for the help.
Essentially the key here is that in your Camel BlueprintTestSupport class, inside the test method, that starts the given scenario you need to add this.setUp(). See the code below:
In Cucumber
SRVXXX_FileTransferCamelRunner filetransfer = new SRVXXX_FileTransferCamelRunner();
#Given("^an input file$")
public void an_input_file() throws Throwable {
endpoint.append("file:C:/Camel/input?fileName=input.txt");
}
#When("^client puts the file in the input directory$")
public void client_puts_the_file_in_the_input_directory() throws Throwable {
filetransfer.testPutFile(fileData.toString(), endpoint.toString());
}
#Then("^the integration should move the file to the output directory$")
public void the_integration_should_move_the_file_to_the_output_directory() throws Throwable {
String outputPath = "C:/Camel/output/input.txt";
filetransfer.testFileHasMoved(outputPath);
}
In Camel
#Test
public void testPutFile(String body, String endpoint) throws Exception {
this.setUp();
template.sendBody(endpoint,body);
Thread.sleep(2000);
assertFileNotExists(endpoint);
}

Invoking JAX-WS Web service from Camel

I need to invoke a JAX-WS Web service available on WildFly 8. I've started with a simple example to get started. Here is my Web service:
import javax.jws.WebService;
#WebService
public class HelloWorld implements Hello{
#Override
public String greet(String s) {
return "Hello "+s;
}
}
The WSDL is available at: http://localhost:8080/DemoWS/HelloWorld?wsdl
Taking a look at the Tomcat-CXF example, I have coded the following route:
public class CamelRoute extends RouteBuilder {
private String uri = "cxf:http://localhost:8080/helloWorld?serviceClass=com.sample.HelloWorld";
#Override
public void configure() throws Exception {
from(uri)
.to("log:input")
.recipientList(simple("direct:${header.operationName}"));
from("direct:greet")
.process(new Processor() {
public void process(Exchange exchange) throws Exception {
String id = exchange.getIn().getBody(String.class);
exchange.getOut().setBody(id);
}
})
.to("log:output");
}
}
By running the above code in a Camel Context, the following error is returned:
Exception in thread "main" org.apache.camel.FailedToCreateRouteException: Failed to create route route1: Route[[From[cxf:http://localhost:8080/helloWorld?serviceClas... because of Failed to resolve endpoint: cxf://http://localhost:8080/helloWorld?serviceClass=com.sample.HelloWorld due to: No component found with scheme: cxf
at org.apache.camel.model.RouteDefinition.addRoutes(RouteDefinition.java:177)
at org.apache.camel.impl.DefaultCamelContext.startRoute(DefaultCamelContext.java:731)
at org.apache.camel.impl.DefaultCamelContext.startRouteDefinitions(DefaultCamelContext.java:1803)
at org.apache.camel.impl.DefaultCamelContext.doStartCamel(DefaultCamelContext.java:1589)
at org.apache.camel.impl.DefaultCamelContext.doStart(DefaultCamelContext.java:1453)
at org.apache.camel.support.ServiceSupport.start(ServiceSupport.java:60)
at org.apache.camel.impl.DefaultCamelContext.start(DefaultCamelContext.java:1421)
at com.sample.Main.main(Main.java:15)
Caused by: org.apache.camel.ResolveEndpointFailedException: Failed to resolve endpoint: cxf://http://localhost:8080/helloWorld?
serviceClass=com.sample.HelloWorld due to: No component found with scheme: cxf
It seems I'm not even able to invoke it. Any help ?
Thannks
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-cxf</artifactId>
</dependency>

Resources