org.testng.TestNGException: Method tearDown requires 1 parameters but 0 were supplied in the #Configuration annotation - cucumber

I am not able to understand what is required as parameter, can anyone help me with this.
I have written below code:-
#Test(groups = "cucumber", description = "Runs Cucumber Feature", dataProvider = "features")
public void feature(CucumberFeatureWrapper cucumberFeature) throws Exception {
testNGCucumberRunner.runCucumber(cucumberFeature.getCucumberFeature());
}
#AfterMethod(alwaysRun = true)
public void tearDown(Scenario scenario) {
scenario.write("Finished Scenario");
if (scenario.isFailed()) {
String screenshotName = scenario.getName().replaceAll(" ", "_");
try {
File sourcePath =((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
File destinationPath = new File(System.getProperty("user.dir") + "/Screenshots/" + screenshotName + ".png");
Files.copy(sourcePath, destinationPath);
Reporter.addScreenCaptureFromPath(destinationPath.toString());
} catch (IOException e) {
}
driver.close();
}
}
And I am getting below error:-
FAILED CONFIGURATION: #AfterMethod tearDown
org.testng.TestNGException: Method tearDown requires 1 parameters but
0 were supplied in the #Configuration annotation.

You cannot pass a Cucumber Scenario object to a TestNg configuration method. The AfterMethod will be called by TestNg and will not be able to inject the Scenario object. For a list of objects that are injected automatically refer to this - http://testng.org/doc/documentation-main.html#native-dependency-injection
Either use the After annotation of Cucumber and pass the Scenario object.
#cucumber.api.java.After
public void tearDown(Scenario scenario)
Or use the AfterMethod of TestNg and pass the ITestResult object.
#org.testng.annotations.AfterMethod
public void tearDown(ITestResult result)

Related

How to attach screenshot to steps using AbstractTestNGCucumberTests?

I want to attach screenshot to steps that is generated cucumber html report. My project use AbstractTestNGCucumberTests.
This is my takeScreenshot method:
public static void takeScreenshot(io.cucumber.core.api.Scenario scenario,
WebDriver driver, File screenShotFile) {
final byte[] screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);
scenario.embed(screenshot, "image/png");
try {
OutputStream os = new FileOutputStream(screenShotFile);
os.write(screenshot);
Log.debug("Successfully save screenshot");
os.close();
} catch (Exception ex) {
Log.error("Exception : " + ex);
}
}
I try to get Scenario by declaring anotation io.cucumber.java.Before
But Scenario is null
Please help me how to get io.cucumber.core.api.Scenario or another way to attach screenshot in steps for reporting
I fixed my problem. Cucumber hook #Before is just run in location that is defined in #CucumberOptions(glue=my-path). My Class TestSuiteMaster is in another path, so Scenario is null.
I created a class CucumberHook in directory stepDefinition and take screen shot method in hook #After, everything work great.
This is my CucumberHook class:
public class CucumberHook extends WebTestSuiteMaster {
#After
public void take_screenshot_after_finished_scenario(Scenario scenario) {
String imageFileName = "Screen shot-" + scenario.getName() + "-"
+ new SimpleDateFormat("MM-dd-yyyy_HH-mm").format(new Date()) + ".png";
File imageFile = new File(System.getProperty("user.dir") + "//screenshots//" + imageFileName);
SeleniumWebHelper.takeScreenshot(scenario, driver, imageFile);
}
}

Inconvertible types; cannot cast 'io.cucumber.java.Scenario' to 'cucumber.runtime.ScenarioImpl'

I've updated my Cucumber version to 5.4.2 and this piece of code stopped working due to a Inconvertible types; cannot cast 'io.cucumber.java.Scenario' to 'cucumber.runtime.ScenarioImpl' error.
Field field = FieldUtils.getField((scenario).getClass(), "stepResults", true);
Any way I could get it back to working?
This is the whole piece of code as per this SO post
private static String logError(Scenario scenario) {
Field field = FieldUtils.getField((scenario).getClass(), "stepResults", true);
if (field != null) {
field.setAccessible(true);
try {
ArrayList<Result> results = (ArrayList<Result>) field.get(scenario);
for (Result result : results) {
if (result.getErrorMessage() != null)
if (result.getErrorMessage().length() >= 10000) {
return FAILED_COMMENT + "\n" + result.getErrorMessage().substring(0, 10000);
} else {
return FAILED_COMMENT + "\n" + result.getErrorMessage();
}
}
} catch (Exception e) {
return FAILED_COMMENT;
}
}
return FAILED_COMMENT;
}
Many thanks.
By using reflection to reach into a frameworks internals you're depending on implementation details. This is a bad practice, when ever the framework changes its implementation your code may break.
Hooks in Cucumber are designed to manipulate the test execution context before and after a scenario. They're not made to report on the test execution itself. Reporting is cross cutting concern and best managed by using the plugin system.
For example:
package com.example;
import io.cucumber.plugin.ConcurrentEventListener;
import io.cucumber.plugin.event.EventPublisher;
import io.cucumber.plugin.event.Result;
import io.cucumber.plugin.event.Status;
import io.cucumber.plugin.event.TestCase;
import io.cucumber.plugin.event.TestCaseFinished;
public class MyTestListener implements ConcurrentEventListener {
#Override
public void setEventPublisher(EventPublisher publisher) {
publisher.registerHandlerFor(TestCaseFinished.class, this::handleTestCaseFinished);
}
private void handleTestCaseFinished(TestCaseFinished event) {
TestCase testCase = event.getTestCase();
Result result = event.getResult();
Status status = result.getStatus();
Throwable error = result.getError();
String scenarioName = testCase.getName();
String id = "" + testCase.getUri() + testCase.getLine();
System.out.println("Testcase " + id + " - " + status.name());
}
}
When using JUnit 4 and TestNG you can activate this plugin using:
#CucumberOptions(plugin="com.example.MyTestListener")
With JUnit 5 you add it to junit-platform.properties:
cucumber.plugin=com.example.MyTestListener
Or if you are using the CLI
--plugin com.example.MyTestListener

Unable to set multiple expectation with MockWebServiceServer

I am using a MockWebServiceServer to test the REST APIs. I am passing the values to it using #Runwith(Parameterized.class).
#RunWith(Parameterized.class)
public class MyAPITest {
protected static MockWebServiceServer mockServer;
private Message message;
public MyAPITest(Message messageIn) {
this.message = messageIn;
}
#BeforeClass
public static void setup(){
mockServer = MockWebServiceServer.createServer(applicationContext);
}
#Test
public final void testMethod() throws Throwable {
Source reqPayload1 = new StringSource("...");
Source reqPayload2 = new StringSource("...");
Source resPayload1 = new StringSource("...");
Source resPayload2 = new StringSource("...");
mockServer.expect(RequestMatchers.payload(reqPayload1 )).andRespond(ResponseCreators.withPayload(resPayload1 ));
//Unable to add below line as it throws exception. Unable to set multiple expectation
//mockServer.expect(RequestMatchers.payload(reqPayload2 )).andRespond(ResponseCreators.withPayload(resPayload2 ));
myClass.onMessage(this.message);
mockServer.verify();
}
#Parameters
public static Collection<Object[]> getParameters() {
//Read input data from file
}
}
Code works fine when I've only 1 input.
But it throws exception when I've more than one input.
java.lang.IllegalStateException: Can not expect another connection, the test is already underway
at org.springframework.util.Assert.state(Assert.java:385)
at org.springframework.ws.test.client.MockWebServiceMessageSender.expectNewConnection(MockWebServiceMessageSender.java:64)
at org.springframework.ws.test.client.MockWebServiceServer.expect(MockWebServiceServer.java:162)
at com.rakuten.gep.newsletter.batch.ExacttargetMQJobTest.testOnMessage(ExacttargetMQJobTest.java:82)
I'm using Spring 3.2. I want to test my api with multiple inputs.

NoClassDefFoundError in j2me

I have build a jar file and trying to use it in j2me application. I have included the jar in the build path and imported the required classes as well. But when I run my j2me application I am getting NoClassDefFound Error in the line where I am trying to instantiate the class which is present in the jar.
I can instantiate the classes of the jar in the java project but not in j2me.
Below is the error log:
WARNING - MMA -
C:/Builds/jme-sdk/javacall-javame-sdk-305/implementation/share/jsr135_mmapi/ju_mmconfig.c
line 801: caps: optional settings missing: SuspendBehavior
java.lang.NoClassDefFoundError: com/canvasm/ida/gps/LocationUpdater
- com.test.ida.HelloIDA.(HelloIDA.java:11)
- java.lang.Class.newInstance(), bci=0
- com.sun.midp.main.CldcMIDletLoader.newInstance(), bci=46
- com.sun.midp.midlet.MIDletStateHandler.createMIDlet(), bci=66
- com.sun.midp.midlet.MIDletStateHandler.createAndRegisterMIDlet(), bci=17
- com.sun.midp.midlet.MIDletStateHandler.startSuite(), bci=27
- com.sun.midp.main.AbstractMIDletSuiteLoader.startSuite(), bci=52
- com.sun.midp.main.CldcMIDletSuiteLoader.startSuite(), bci=8
- com.sun.midp.main.AbstractMIDletSuiteLoader.runMIDletSuite(), bci=161
- com.sun.midp.main.AppIsolateMIDletSuiteLoader.main(), bci=26 javacall_lifecycle_state_changed() lifecycle: event is
JAVACALL_LIFECYCLE_MIDLET_SHUTDOWN status is JAVACALL_OK
TestApp(j2me app):
import com.test.gps.LocationUpdater;
public class Hello extends MIDlet {
public Hello() {
LocationUpdater loc = new LocationUpdater();
System.out.println("Loc updater object :"+loc.toString());
}
protected void destroyApp(boolean arg0) throws MIDletStateChangeException {
// TODO Auto-generated method stub
}
protected void pauseApp() {
// TODO Auto-generated method stub
}
protected void startApp() throws MIDletStateChangeException {
}
}
JAR file main class:
public class LocationUpdater {
private boolean isUpdateSuccess = false;
public static void main(String[] args){
}
public boolean updateLocation(final String serverUrl, final String userMSISDN) throws LocationException{
AppConstants.url = serverUrl;
AppConstants.msisdn = userMSISDN;
LocationCanvas loc = new LocationCanvas();
isUpdateSuccess = loc.getLocation(serverUrl, userMSISDN);
return isUpdateSuccess;
}
}
LocationCanvas class:
public class LocationCanvas {
private Location location;
private LocationProvider locationProvider;
private Coordinates coordinates;
private Criteria criteria;
private Timer tm;
private double lat, lon;
private String posturl;
private boolean status,updateStatus;
public LocationCanvas() {
}
public boolean getLocation(String url, String msisdn) {
tm = new Timer();
criteria = new Criteria();
criteria.setHorizontalAccuracy(500);
try {
locationProvider = LocationProvider.getInstance(criteria);
if (locationProvider != null) {
tm.wait(4000);
try {
location = locationProvider.getLocation(2000);
} catch (Exception e) {
System.out.println(e.getMessage());
}
coordinates = (Coordinates)location.getQualifiedCoordinates();
if (coordinates != null) {
// Use coordinate information
lat = coordinates.getLatitude();
lon = coordinates.getLongitude();
System.out.println("Latitude :"+lat);
System.out.println("Longitude :"+lon);
}
posturl = url + "?IMEI=" + msisdn
+ "&positioningtype=" + "gps" + "&locationdata=" + lat
+ "," + lon;
}else{
//return false.. cos location provider is null
updateStatus = false;
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
return updateStatus;
}
error log:
Exception in thread "main" java.lang.NoClassDefFoundError:
javax/microedition/location/Coordinates
at com.canvasm.ida.gps.LocationUpdater.updateLocation(LocationUpdater.java:17)
at com.test.HelloTest.main(HelloTest.java:10)
Caused by: java.lang.ClassNotFoundException: javax.microedition.location.Coordinates
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
Any help would be appreciated.
It specifies that class file present at compile time is not found at run time.Check for build time and run time classpaths .
Finally able to solve the issue.
The problem was not in the code. It was due to the compilation issue.
First of all To solve the NoClassDefFoundError , I had to right click on the project and in the build path-> order and export -> check the jar that you have added.
Later while running I faced classFormatError 56.
The jar file which was created, was compiled using 1.6v.
And the j2me application was getting compiled with 1.3v.
I had to recompile my library project with 1.3v and create a jar out of it and used it in the j2me application.
Here is the link to guide: Build a Project from the Command Line - Java ME SDK

How do you invoke a Runnable using Spring Framework?

I have a service that needs to invoke a runnable class.
Here are the lines of code that are being used in my service.
#Autowired
private LinkBrc2MemberProfile brcTask;
// Background Task.
SimpleAsyncTaskExecutor sate = new SimpleAsyncTaskExecutor();
sate.createThread(new LinkBrc2MemberProfile(user));
Here is my Runnable class
#Service
public class LinkBrc2MemberProfile implements Runnable {
private final Logger log = LoggerFactory.getLogger(LinkBrc2MemberProfile.class);
#Autowired
private LoyaltyDao dao;
private Member member;
public LinkBrc2MemberProfile() {
super();
}
public LinkBrc2MemberProfile(Member member) {
this.member = member;
}
public void run() {
log.debug("*** Member User Name: " + member.getString("USER_NAME"));
String emailAddress = member.getString("USER_NAME");
Map<String, Object> map = dao.findBrcByEmailAddress( emailAddress );
log.debug("==========================================================");
if( ! map.isEmpty() ) {
try {
//a.CUSTOMER_ID, a.EMAIL_ADDRESS, b.card_no
String customerId = (String) map.get("CUSTOMER_ID");
String brcCardNumber = (String) map.get("CARD_NO");
log.debug("\ncustomerId: " + customerId + " brcCardNumber: " + brcCardNumber);
if(!brcCardNumber.equals("")) {
// Add the Be Rewarded Card.
HashMap<String, String> userAttributes = new HashMap<String, String>();
String brcNumber = member.getString("BREWARDED_CARD_NO");
if (brcNumber.equals("")) {
userAttributes.put("BREWARDED_CARD_NO", brcCardNumber);
try {
member.putAll(userAttributes);
} catch (Exception e) {
String errorMessage = "Unable to save user's BRC information due to: " + e.getMessage();
log.error("{}", errorMessage);
}
}
}
} catch (Exception e) {
log.error(e.getMessage());
e.printStackTrace();
}
}
}
I'm not seeing any errors in the log but at the same time it does not appear to be invoking the Runnable class. Am I missing an annotation somewhere? Are there any good examples that you can point me to, the only ones I have found use XML files to configure the runnable class I would like to use annotations. Thanks in Advance.
I've updated my service to do the following.
Please help, my DAO is NULL so it looks like my #Autowired in my Runnable class is not wiring it in.
I've added the following bean to my bean-config.xml file.
<bean id="brcType" class="com.ws.ocp.service.LinkBrc2MemberProfile" scope="prototype"/>
I removed my #Autowired annotation and added the following to my service class.
ClassPathResource rsrc = new ClassPathResource("bean-config.xml");
XmlBeanFactory factory = new XmlBeanFactory(rsrc);
LinkBrc2MemberProfile brcTask = (LinkBrc2MemberProfile) factory.getBean("brcType");
SimpleAsyncTaskExecutor sate = new SimpleAsyncTaskExecutor();
// Set Member attribute
brcTask.setMember(user);
// Executer
sate.execute(brcTask);
Why is my dao still null?
The runnable will throw a NullPointerException, since you create it yourself (using the new operator), instead of letting Spring create it. This obviously means that the autowired DAO attribute won't be autowired, which will lead to a NPE when calling dao.findBrcByEmailAddress(...).
You should get your Runnable instance from the bean factory (as a prototype), set its member attribute, and then submit it to the executor.
To answer your question of how to properly use a Prototype-Bean, this is my favorite way:
#Component
abstract class MyBean {
/* Factory method that will be installed by Spring */
#Lookup
protected abstract YourPrototypeBean createBean();
void someCode() {
YourPrototypeBean bean = createBean();
}
}
Since it's a factory method, you can create as many instances as you like.

Resources