Using TestFX with Cucumber - java

I'm trying to use Cucumber with TestFX but cant get any nodes from the application.
I've another class of TestFX that works fine and another class of Cucumber which also works fine. But I'm getting
org.loadui.testfx.exceptions.NoNodesFoundException: No nodes matched 'TextInputControl has text "Can you find this label"'.
TestFXBase :
import javafx.scene.Node;
import javafx.scene.input.KeyCode;
import javafx.scene.input.MouseButton;
import javafx.stage.Stage;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.testfx.api.FxToolkit;
import org.testfx.framework.junit.ApplicationTest;
import java.util.concurrent.TimeoutException;
public class TestFXBase extends ApplicationTest {
private static boolean isHeadless = false;
#BeforeClass
public static void setupHeadlessMode() {
if(isHeadless){
System.setProperty("testfx.robot", "glass");
System.setProperty("testfx.headless", "true");
System.setProperty("prism.order", "sw");
System.setProperty("prism.text", "t2k");
System.setProperty("java.awt.headless", "true");
}
}
#Before
public void setUpClass() throws Exception {
ApplicationTest.launch(Main.class);
}
#Override
public void start(Stage stage) throws Exception {
stage.show();
}
#After
public void afterEachTest() throws TimeoutException {
FxToolkit.hideStage();
release(new KeyCode[]{});
release(new MouseButton[]{});
}
/* Helper method to retrieve Java FX GUI Components */
public <T extends Node> T find (final String query){
return (T) lookup(query).queryAll().iterator().next();
}
}
This is my testfx base class and my cucumber runner and stepdefs extends this.
StepDefs:
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import org.junit.Test;
public class MyStepdefs extends TestFXBase {
#Test
#Given("^That \"([^\"]*)\" Exists$")
public void thatExists(String arg0) throws Throwable {
rightClickOn("#rect");
}
#Test
#Then("^Which is \"([^\"]*)\"$")
public void whichIs(String arg0) throws Throwable {
System.out.println(arg0);
}
}
Runner:
import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;
import org.junit.runner.RunWith;
#RunWith(Cucumber.class)
#CucumberOptions(plugin = { "pretty" })
public class MyRunner extends TestFXBase{}
Feature:
Feature: Do label texts exist?
Scenario: Can you find this label text
Given That "Can you find this label" Exists
Then Which is "great"
So, the parameter is passed but TestFX dont start application in my cucumber runner, just tries to find nodes. There is a class that extends TestFXBase and works perfectly. How can I solve this issue?
Edit: My dependencies are
<dependency>
<groupId>org.loadui</groupId>
<artifactId>testFx</artifactId>
<version>3.1.2</version>
</dependency>
<dependency>
<groupId>org.jfxtras</groupId>
<artifactId>openjfx-monocle</artifactId>
<version>1.8.0_20</version>
</dependency>
<dependency>
<groupId>org.testfx</groupId>
<artifactId>testfx-core</artifactId>
<version>4.0.6-alpha</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<version>1.3</version>
</dependency>
<dependency>
<groupId>org.testfx</groupId>
<artifactId>testfx-junit</artifactId>
<version>4.0.6-alpha</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-java</artifactId>
<version>1.2.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-junit</artifactId>
<version>1.2.5</version>
<scope>test</scope>
</dependency>

Solution here is to move content of setupHeadlessMode and setUpClass methods to TestFXBase class initializer:
static {
if (isHeadless) {
System.setProperty("testfx.robot", "glass");
System.setProperty("testfx.headless", "true");
System.setProperty("prism.order", "sw");
System.setProperty("prism.text", "t2k");
System.setProperty("java.awt.headless", "true");
}
try {
ApplicationTest.launch(Main.class);
} catch (Exception e) {
// oh no
}
}

Related

Null pointer Exception when injecting a rest-assured #Steps into spring-boot Test

Am new to springboot and am trying to integrate Integration Tests using Rest-assured to test my Rest-Api.
Am getting NPE when injecting #Steps into SpringBoot Test.I'm introducing a step class to improve on re-usability code.This test runs well if the step method is in the IT-class.I tried #Component annotation but it didn't work
Step class
import net.thucydides.core.annotations.Step;
import org.apache.http.HttpStatus;
import static com.jayway.restassured.RestAssured.when;
public class StaffSteps {
protected static String BASE_STAFF_URL = "/api/v1a/staff/";
protected static Staff staff;
#Step
public StaffSteps getStaffMemberById(String id){
staff = when().get(BASE_STAFF_URL+id)
.then().assertThat()
.statusCode(HttpStatus.SC_OK)
.extract()
.as(Staff.class);
return this;
}
#Step
public Staff getStaff(){return staff;}
}
import net.thucydides.core.annotations.Steps;
import org.apache.http.HttpStatus;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.Arrays;
import java.util.List;
import static com.jayway.restassured.RestAssured.when;
#RunWith(SpringJUnit4ClassRunner.class)
public class StaffControllerIT extends BaseTest {
#Steps
private StaffSteps staffSteps;
#Before
public void setUp(){
}
#Test
public void getStaffMemberById(){
String id ="ff8081817049a34e017049a379320000";
Staff staff = staffSteps.getStaffMemberById(id).getStaff();
System.err.println(staff);
}
When i run this test, staffSteps is null.
Here is my dependency i used
<dependency>
<groupId>net.serenity-bdd</groupId>
<artifactId>serenity-core</artifactId>
<version>1.9.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<version>3.0.0</version>
<scope>test</scope>
</dependency>
Please let me know if you need more information on this. Thanks
Solution using SpringRunner:
Annotate the steps with #Bean and #StepScope, and as a result, this object will share its lifetime with StepExecution.
public class StaffStepsConfig {
protected static String BASE_STAFF_URL = "/api/v1a/staff/";
protected static Staff staff;
#Bean
#StepScope
public StaffSteps getStaffMemberById(String id){
staff = when().get(BASE_STAFF_URL+id)
.then().assertThat()
.statusCode(HttpStatus.SC_OK)
.extract()
.as(Staff.class);
return this;
}
#Bean
#StepScope
public Staff getStaff(){return staff;}
}
In the Test class, the spring-batch-test dependency provides a set of useful helper methods and listeners that can be used to configure the Spring Batch context during testing.
#RunWith(SpringRunner.class)
//#SpringBatchTest
//#SpringBootTest
#EnableAutoConfiguration
#ContextConfiguration(classes = { StaffStepsConfig.class })
#DirtiesContext(classMode = ClassMode.AFTER_CLASS)
public class StaffControllerIT extends BaseTest {
#Autowired
private StaffSteps staffSteps;
#Before
public void setUp(){
}
#Test
public void getStaffMemberById(){
String id ="ff8081817049a34e017049a379320000";
Staff staff = staffSteps.getStaffMemberById(id).getStaff();
System.err.println(staff);
}
}
Note: This runner recognizes #SpringBootTest . I think the problem is in the way the test outcomes are generated. The steps are not being read by Serenity. Spring will inject #Autowired classes, and #serenity will inject #steps classes. I assume this happens because serenity and spring are creating components in different contexts .
required dependencies in your pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-batch</artifactId>
<version>2.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.1.9.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-test</artifactId>
<version>4.2.0.RELEASE</version>
<scope>test</scope>
</dependency>

TooLittleActualInvocations:

I try to use mock to verify method for serveral times.But I meet this problem.
org.mockito.exceptions.verification.TooLittleActualInvocations:
personDao.update(isA(com.zhaolu08.Person));
Wanted 3 times:
-> at com.zhaolu08.PersonServiceTest.testUpdate(PersonServiceTest.java:32)
But was 1 time:
while my code is:
package com.zhaolu08;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.isA;
import static org.mockito.Mockito.eq;
public class PersonServiceTest {
private PersonDao mockDao;
private PersonService personService;
#Before
public void setUp() throws Exception {
//模拟PersonDao对象
mockDao = mock(PersonDao.class);
when(mockDao.getPerson(1)).thenReturn(new Person(1, "Person1"));
when(mockDao.update(isA(Person.class))).thenReturn(true);
personService = new PersonService(mockDao);
}
#Test
public void testUpdate() throws Exception {
boolean result = personService.update(1, "new name");
Assert.assertTrue("must true", result);
verify(mockDao, times(2)).getPerson(eq(1));
verify(mockDao, times(3)).update(isA(Person.class));
}
}
I can't find out the problem. I try some methods. They did not work.
My IDE is idea.
Maven pom is:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.10.19</version>
</dependency>
I can't find out why it doesn't work. It is just a simple demo. It's too wired.
It seems due to the fact that you are expecting personDao.update to be invoked 3 times and actually in your method personService.update(1, "new name"); it is getting invoked only 1 time

Is there any way to test an anonymous inner class using junit?

I have the following class that I would like to test. Having to test an anonymous inner class is proving to be very difficult. Any help would be appreciated.
#Configuration
public class CustomErrorConfiguration {
#Bean
public ErrorAttributes errorAttributes() {
return new DefaultErrorAttributes() {
#Override
public Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes,
boolean includeStackTrace) {
Map<String, Object> errorAttributes = super.getErrorAttributes(requestAttributes, includeStackTrace);
errorAttributes.remove("timestamp");
errorAttributes.remove("status");
errorAttributes.remove("exception");
errorAttributes.remove("path");
if (errorAttributes.containsKey("error") && errorAttributes.containsKey("message")) {
Map<String, Object> attr = new HashMap<>();
attr.put("message", errorAttributes.get("message"));
return attr;
}
return errorAttributes;
}
};
}
}
This should be the minimum needed to test your inner class:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
#RunWith(SpringRunner.class)
#ContextConfiguration
public class BeanTest {
#Autowired
ErrorAttributes errorAttributes;
#Test
public void testMyBean() {
RequestAttributes requestAttributes = new RequestAttributes();
System.out.println(errorAttributes.getErrorAttributes(requestAttributes, true));
}
#Configuration
#ComponentScan(basePackages = "package.where.your.configuration.is")
public static class SpringTestConfig {
}
}
This test does a few things:
It leverages SpringRunner.class to create an ApplicationContext for you test.
The #ContextConfiguration annotation picks up the the static nested class SpringTestConfig. This class does the heavy lifting and actually scans base packages looking for other classes marked with Configuration, Bean, Component, etc. This will discover your Configuration which will in turn cause instantiation of your Bean.
Since the application context is now setup we can inject the bean with #Autowired as you would in normal application code.
I needed the following maven dependencies to accomplish this (junit >= 4.12 required). All are available in maven central:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.0.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>

Spring AOP before annotation is not working

I am trying to implement AOP concept using Spring Boot. But before annotation is not working.
This is my code,
POM.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
Application.properties
server.port=6500
spring.aop.proxy-target-class=true
Main:
package com.techno.theater;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.techno.theater.services.SampleService;
#SpringBootApplication
public class DigitalTheaterApplication {
private static Logger logger=LoggerFactory.getLogger(DigitalTheaterApplication.class);
public static void main(String[] args) {
SpringApplication.run(DigitalTheaterApplication.class, args);
new SampleService().sample();
}
}
Sample Service:
package com.techno.theater.services;
import org.springframework.stereotype.Service;
#Service
public class SampleService {
public void sample(){
System.out.println("Sample method inovking");
}
}
Aspect class
package com.techno.theater.aop;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
#Aspect
#Component
public class AspectService {
#Before("execution(* com.techno.theater.services.SampleService.sample())")
public void beforeSampleMethod() {
System.out.println("Sample method aspect");
}
}
Here I am invoking sample method from DigitalTheaterApplication class but before execute this method my aspect method should be executed but it's not working am not sure do I need to add some configuration.
public static void main(String[] args) {
SpringApplication.run(DigitalTheaterApplication.class, args);
new SampleService().sample();
}
The code above is the problem, to be precise the new SampleService().sample(); is what is flawed in your code. You are creating a new instance outside the scope of Spring and as such it will not be exposed to AOP.
Instead what you should do, is retrieve the SampleService from the ApplicationContext.
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(DigitalTheaterApplication.class, args);
ctx.getBean(SampleService.class).sample();
}
This will get the Spring created, and proxied, instance, with AOP applied.
Another way, without messing around with the ApplicationContext is to create a CommandLineRunner which will be executed during startup.
public static void main(String[] args) {
SpringApplication.run(DigitalTheaterApplication.class, args);
}
#Bean
public CommandLineRunner tester(SampleService service) {
return args -> service.sample();
}
Something like that will also invoke the sample method on the Spring managed instance without having to get it yourself.

error: Type mismatch: cannot convert from Test to Annotation

I am newbie to junit Mockito framework, I have mocked the Dependency Injection using powermock framework, but I am getting error in eclipse on #Test annotation the error is "Type mismatch: cannot convert from Test to Annotation"
package org.singh.util.MockitoDemo;
import static org.mockito.Matchers.anyString;
import static org.powermock.api.mockito.PowerMockito.doNothing;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static org.powermock.api.mockito.PowerMockito.when;
import static org.powermock.api.support.membermodification.MemberMatcher.method;
import org.junit.*;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest({ExampleUtil.class, ExamplePojo.class})
public class ExamplePojoTest{
#Test
public void testMethodMakingPrivateMethodCall() throws Exception {
ExamplePojo spyExamplePojo = PowerMockito.spy(new ExamplePojo());
when(spyExamplePojo, method(ExamplePojo.class, "privateMethod", String.class)).withArguments(anyString()).thenReturn("test test");
String result = spyExamplePojo.methodMakingPrivateMethodCall("test");
Assert.assertEquals("test test", result);
}
}
maven dependencies are
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito</artifactId>
<version>1.6.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>1.6.1</version>
<scope>test</scope>
</dependency>
</dependencies>
When you see this error , it means you have a class name as “Test” in the same package.
Just rename that class name and it will work fine!!!!

Categories