Using PowerMock with Spock - groovy

I have a class with a few static methods.I need to Mock these static methods. I know PowerMock does this,but I was not able to find any tutorials/materials that shed some light on "Spock+PowerMock" integration. I prefer Spock to Junit,hence the conundrum. Is there a way of getting these 2 frameworks to play ball?Any help is much appreciated.Sample code,even more so.
Update: Current Status of the Approach
Spock behaving weirdly

I was stuck here for a while too. After searching for hours, I saw this github repo: https://github.com/kriegaex/Spock_PowerMock.
I tried adding a PowerMockRule which essentially enabled me to use PowerMock together with Spock. I had to add these dependencies. Version is at 1.5.4
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4-rule</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-classloading-xstream</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
My class looks like this:
import org.junit.Rule
import org.mockito.Mockito
import org.powermock.api.mockito.PowerMockito
import org.powermock.core.classloader.annotations.PrepareForTest
import org.powermock.modules.junit4.rule.PowerMockRule
import spock.lang.Specification
#PrepareForTest([SomeStaticClass.class])
public class FlightFormSpec extends Specification {
#Rule PowerMockRule powerMockRule = new PowerMockRule();
def "When mocking static"() {
setup :
PowerMockito.mockStatic(SomeStaticClass.class)
when :
Mockito.when(SomeStaticClass.someStaticMethod()).thenReturn("Philippines!");
then :
SomeStaticClass.someStaticMethod() == "Philippines!"
}
}
Here is another resource: https://github.com/jayway/powermock/wiki/powermockrule

There is no special integration; your best bet is to try and use PowerMock "as-is". From what I remember, PowerMock used to have problems with Groovy, and I don't know if this has been solved. And if I'm not mistaken, PowerMock rewrites the byte code of test classes, so the next question is if it works with Spock. Let us know what you find.

Since Powermock Version 1.6.0, powermock allows the delegation of the test runner.
This allows the wrapping of the Spock test runner (Sputnik) within the PowerMock test runner framework. Sputnik will then start the test case specifications, and still allow the use of the PowerMock framework.
With JUnit4 and Powermock, I use the following template for accessing static classes.
The test class:
package mypackage;
import org.junit.runner.RunWith
import org.powermock.api.mockito.PowerMockito
import org.powermock.core.classloader.annotations.PrepareForTest
import org.powermock.modules.junit4.PowerMockRunner
import org.powermock.modules.junit4.PowerMockRunnerDelegate
import org.spockframework.runtime.Sputnik
import spock.lang.Specification
#RunWith(PowerMockRunner.class)
#PowerMockRunnerDelegate(Sputnik.class)
#PrepareForTest([MyStaticMethodClass.class])
class MyTestForClassTest extends Specification {
def myStaticMethodClass
def setup() {
PowerMockito.mockStatic(MyStaticMethodClass.class)
myStaticMethodClass= Mock(MyStaticMethodClass)
PowerMockito.when(MyStaticMethodClass.getInstance()).thenReturn(myStaticMethodClass)
}
#Unroll
def "#TestCase policy RF210 triggered"() {
given: "a product list for the policy"
myStaticMethodClass.someInstanceMethod() >> "my return value"
classUnderTest = new ClassUnderTest()
...
The dependencies
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.10.19</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>1.7.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito</artifactId>
<version>1.7.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-core</artifactId>
<version>1.3-groovy-2.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>3.3.0</version>
<scope>test</scope>
</dependency>

Related

Cucumber No features found with JUnit5

I am trying to setup Cucumber in my project. I am following the same configuration from my previous projects but I still have issues with running the tests. Now I am starting to suspect that the issue might be that this project is using JUnit 5 instead of 4. I have added junit4 to the build options as well to be able to execute the #RunWith annotation with jUnit4, but I still get the same error ( No features found at classpath ) .
The runner class is as follows:
import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
import io.cucumber.junit.CucumberOptions.SnippetType;
import org.junit.runner.RunWith;
#RunWith(Cucumber.class)
#CucumberOptions(features = "classpath:resources", plugin = {"pretty", "html:target/reports/cucumber/html",
"json:target/cucumber.json", "usage:target/usage.jsonx",
"junit:target/junit.xml"}, snippets = SnippetType.CAMELCASE)
public class TestCucumberRunner {
}
The structure of the folders is following:
Here is the pom configuration:
As far as I can see, the #RunWith annotation is imported from junit4 and not 5, so why is this issue happening?
I also tried adding the feature file in the same folder with the runner, as well as adding the exact path in the feature option, but still the same error.
You can run Cucumber tests with Junit 5 and via maven. I searched a lot before finding the right configuration.
The important steps :
add maven-surefire-plugin in you plugins pom, so cucumber tests can bu run from mvn test
use the same structure for features in your test resources as your cucumber java steps (if your test class is in com.example.usescase, locate your feature in resources/com/example/usecase )
add cucumber launcher on the root folder of your java tests. I can be annotated with just #Cucumber
Courtesy to https://github.com/bonigarcia , I really found how to make it work thanks to its repository https://github.com/bonigarcia/mastering-junit5/tree/master/junit5-cucumber
With Junit5, you just need to write runner like below :
#Suite
#SelectClasspathResource("Features Folder")
public class Runner {
}
For using tags, you can put the tags properties in junit-platform.properties.
You can refer for pom dependencies - https://github.com/cucumber/cucumber-java-skeleton/blob/main/pom.xml
I was facing a lot of issues. I followed above and could run my cucumber tests with Junit5 without any issues.
There might be some problems with the step definitions as well (cann't tell exactly by looking at the info), looks like that Cucumber cannot find your feature file step definitions.
please have a look on cucumber documentation
You need to specify the path to your step definitions (glue path) correctly.
Usually cucumber jvm will search in the package (or sub-packages) of the runner class. However, you can also mention explicitly by the following way:
#CucumberOptions(glue = ["", "", ""])
Setting up Cucumber with JUnit 5 has not been documented very well (yet). The trick is to use the cucumber-junit-platform-engine as described in https://cucumber.io/docs/cucumber/api/.
For example:
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<version>6.6.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit</artifactId>
<version>6.6.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit-platform-engine</artifactId>
<version>6.6.1</version>
<scope>test</scope>
</dependency>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<properties>
<configurationParameters>
cucumber.plugin=pretty,html:target/site/cucumber-pretty.html
cucumber.publish.quiet=true
cucumber.publish.enabled=false
</configurationParameters>
</properties>
</configuration>
</plugin>
</plugins>
</build>
Now use the maven-surefire-plugin to inject Cucumber parameters, since the 'old' JUnit 4 #CucumberOptions annotation won't have any effect anymore.
More Cucumber configuration options can be found here: https://github.com/cucumber/cucumber-jvm/tree/main/junit-platform-engine#configuration-options
Your Java entry point for your Cucumber tests will now look like this:
#RunWith(Cucumber.class)
public class BDDEntryPointTest {
/*
Entry point class for Cucumber test.
It will automatically scan for
1. *.feature files in src/test/resources
2. Step definitions in java files under in src/test/java
*/
}
I had similar issues with junit5 and I got it resolved by removing these three dependencies from pom
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.7.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit</artifactId>
<version>${cucumber.version}</version>
<scope>test</scope>
</dependency>
and by keeping these ones
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.7.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<version>${cucumber.version}</version>
<scope>test</scope>
</dependency>
and then your runner class will be just
#Cucumber
public class AcceptanceIT {
}
and step defs would be . No #Test annotations
#Given("I log {string}")
public void logSomething(String teststr ) {
System.out.println("sample text:"+ teststr);
}
Note I am using maven-failsafe here . The runner class name might different if you use other plugin like maven-surefire or use any other mechanism. Here is my maven-failsafe config
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>3.0.0-M5</version>
<executions>
<execution>
<id>integration-test</id>
<goals>
<goal>integration-test</goal>
</goals>
</execution>
<execution>
<id>verify</id>
<goals>
<goal>verify</goal>
</goals>
</execution>
</executions>
<configuration>
<failIfNoTests>false</failIfNoTests>
<testSourceDirectory>${project.basedir}/src/test/java</testSourceDirectory>
<includes>
<include>**/*IT.java</include>
</includes>
</configuration>
</plugin>

Cucumber rerun failed tests and cocatenate results using a testNG runner for cucumber 4.x

I am trying to execute a 2nd round of running only the failed scenarios in order to avoid false alarms because of environment/network/test unstabilities.
I am wondering if there is way to run only a maven command that will perform the following:
1. run all the scenarios that my runner includes in its configuration
2. create the cucumber.json report for this run
3. create a list of the failed scenarios
4. run the list of the failed scenarios
5. change the result of the report created in 1rst run depending on the results of failed tests in 2nd run, so that at the end, only the scenarios that failed in both runs are marked as failed and also there are no duplicates in the final report for those tests that failed at 1rst run (i.e. 2nd run overides the result of 1st run).
I am using cucumber 4.4.0 and testNG runner.
I have tried to use #ExtendedCucumberOptions (http://mkolisnyk.github.io/cucumber-reports/extended-cucumber-runner) and the 1rst run was ok, but the 2nd run was never happened, throwing the following exception:
"Method public void com.github.mkolisnyk.cucumber.runner.ExtendedTestNGRunner.feature(cucumber.api.testng.CucumberFeatureWrapper) requires a #DataProvider named : feature"
I found this issue:
https://github.com/mkolisnyk/cucumber-reports/issues/138
So, it seems that this cucumber-reports library does not support later versions of cucumber and I cannot use #ExtendedCucumberOptions that seemed to provide exactly what I need.
===> My maven dependecies include:
<dependency>
<groupId>com.github.mkolisnyk</groupId>
<artifactId>cucumber-runner</artifactId>
<version>1.3.4</version>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<version>4.4.0</version>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-testng</artifactId>
<version>4.4.0</version>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit</artifactId>
<version>4.4.0</version>
</dependency>
===> And my runner class :
package runners;
import cucumber.api.CucumberOptions;
import cucumber.api.testng.AbstractTestNGCucumberTests;
import org.testng.annotations.DataProvider;
#CucumberOptions(
features = {"src/test/resources/features/"},
glue = {"stepDefinitions"},
tags = {"#magic"},
plugin = {
"pretty"
, "html:target/cucumber"
, "json:target/cucumber/cucumber.json"
, "rerun:target/cucumber/failedTests.txt"
},
monochrome = false
)
public class AreaRunner extends AbstractTestNGCucumberTests {
#Override
#DataProvider(parallel = true)
public Object[][] scenarios() {
return super.scenarios();
}
}
Is there any solution other than #ExtendedCucumberOptions?
The reason the 2nd run never happened is because Retry functionality is applicable for JUnit runner only, as per https://github.com/mkolisnyk/cucumber-reports/issues/167.
Try https://github.com/prashant-ramcharan/courgette-jvm - it has the ability to rerun failing tests similarly to ExtendedCucumberOptions, but this one contains the new Cucumber already.

PhantomJS driver is not getting invoked while using WebDriverManager for my java code

I have been using WebDriverManager to manage drivers for my class file which in turn is used extended to other class files for testing using Selenium.
I am using maven to do the builds, below is the content of my pom.xml file :
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.12.0</version>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.9.8</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.github.bonigarcia</groupId>
<artifactId>webdrivermanager</artifactId>
<version>3.1.1</version>
<scope>test</scope>
</dependency>
</dependencies>
And below is the class file that I am using to invoke the drivers :
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.BeforeTest;
import io.github.bonigarcia.wdm.WebDriverManager;
import io.github.bonigarcia.wdm.PhantomJsDriverManager;
public abstract class GetDriver {
// declare driver
public WebDriver driver;
// Assign the driver
#BeforeTest
public void WebdriverSetUp() {
WebDriverManager.phantomjs().setup();
driver = new PhantomJsDriver();
}
}
Now the problem is that whenever I try to add the phantomjs driver using the below two lines :
WebDriverManager.phantomjs().setup();
driver = new PhantomJSDriver();
It gives me the error, "PhantomJSDriver cannot be resolved to a type". Eclipse suggests me to do any of the below fix :
Create class 'PhantomJSDriver'
Change to 'WebDriver' (org.openqa.selenium)
"Change to 'PhantomJsDriverManager' (io.github.bonigarcia.wdm)"
When I try selecting the third fix which is to change to PhantomJsDriverManager, another error pops up
Type mismatch: cannot convert from PhantomJsDriverManager to WebDriver
For the above error again, Eclipse suggests two fixes :
Add cast to 'WebDriver'
Change type of 'driver' to 'PhantomJsDriverManager'
When I select the second option from above the code changes to
public abstract class GetDriver {
// declare driver
public PhantomJsDriverManager driver;
// Assign the driver
#BeforeTest
public void WebdriverSetUp() {
WebDriverManager.phantomjs().setup();
driver = new PhantomJsDriverManager();
}
}
After the above change I now get the error, "The constructor PhantomJsDriverManager() is not visible".
This issue is happening just for the PhantomJs driver. I tried with chrome driver and it worked like a charm. Please help me as to how can I use webdrivermanager so that I can PhantomJS driver to be used for headless execution of my Selenium code.
I had to move away from using the WebDriverManager for PhantomJS and instead used chrome driver with headless chrome. That fixed the issues I was facing, and finally I was able to do my testing via Jenkins without any issues.
I had same issue so i decide to go with ChromeOptions class instead of PhantomJS driver by setting the value of addArguments as --headless like below:
WebDriverManager.chromedriver().setup();
ChromeOptions options = new ChromeOptions();
options.addArguments("--headless");
options.addArguments("--disable-gpu");
driver = new ChromeDriver(options);

Testng is not executing Code inside Cucumber Hooks

I am new to Selenium,Cucumber Tool and am learning to build a BDD Framework using Selenium,cucumber,maven and TestNG.
I have basically Three Java files-
Test-Runner(src/test/java)
Step-Definition(src/test/java)
TestBase(src/main/java)
I have before and after hooks defined inside TestBase Class
My Test-Runner class has a Plugin defined for Extent-report and also it has #AfterClass annotation which is loading the extent-config.xml-
Now when am running the Feature files, it doesn't execute the #AfterClass annotations, hence skips generating extent Report.
But if I run directly Test-runner file using TestNG, it skips executing Hooks defined in testBase Class-
Code of Test-Runner-
#CucumberOptions(
features={"src/test/resources/Features/login"},
glue={"stepDefinition","src/main/java/Utils/TestBase.java"},
monochrome=true,
plugin={"pretty","html:target/Reports","com.cucumber.listener.ExtentCucumberFormatter:target/cucumber-reports/report.html"}
)
public class Login_Runner extends AbstractTestNGCucumberTests{
#AfterClass
public static void writeExtentReport() {
System.out.println("I am in After Class");
Reporter.loadXMLConfig(new File("src/test/resources/extent-config.xml"));
}
Can anyone help to solve this issue???
Assume the following structure
src/test/java/stepdef/LoginSteps.java
src/test/java/runner/Login_Runner.java
src/test/resources/features/login.feature
pom.xml
LoginSteps.java
implements all steps for `login.feature`
Login_Runner.java
package runner;
import org.testng.annotations.AfterClass;
import cucumber.api.CucumberOptions;
import cucumber.api.testng.AbstractTestNGCucumberTests;
#CucumberOptions(features = "src/test/resources/features", glue = "stepdef")
public class Login_Runner extends AbstractTestNGCucumberTests {
#AfterClass
public static void theAfterClassMethod() {
System.out.println("execute #AfterClass annotated method");
}
}
login.feature
Feature: test
Scenario: login
Given open browser
And start app
When enter details
Then login happens
pom.xml*
<?xml version="1.0" encoding="UTF-8"?>
<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.suboptimal</groupId>
<artifactId>cuke-testng2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-testng</artifactId>
<version>3.0.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<version>3.0.2</version>
<type>jar</type>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>10</maven.compiler.source>
<maven.compiler.target>10</maven.compiler.target>
<surefire.version>2.22.0</surefire.version>
</properties>
</project>
running the test
mvn clean test -Dtest=Login_Runner
produces the output
...
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running runner.Login_Runner
Configuring TestNG with: org.apache.maven.surefire.testng.conf.TestNG652Configurator#5ae63ade
execute #Before annotated method
execute #After annotated method
execute #AfterClass annotated method
1 Scenarios (1 passed)
4 Steps (4 passed)
0m0.023s
when you rename the class Login_Runner to e.g. LoginRunnerTest you can run the test with mvn clean test.
Maybe the runner class name is your original problem and not the missed execution of the #AfterTest method.

Unable to connect mongodb atlas to intellij MongoExplorer

I'm using mongodb atlas for my backend and I'm trying to connect it to Mongo Explorer of intellij
This is the first image for furthur details
This is the second image where I provided the database username and password but still I'm not able to connect.
I have connected to localhost very easily without any problems but this is not connecting...
I'm using Intellij Idea Ultimate 2017.1.3 with student license. I think there is no problem with this particular license and Ide version
Thanks in advance :)
It is very easy steps:
Add these Dependencies in pom.xml file :
<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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
You want to add this code to application.properties file :
spring.data.mongodb.uri= your_uri_here
spring.data.mongodb.database= database_name_here
mongodb+srv://admin:<password>#clust‌​er0-shard-00-01-shj3‌​q.mongodb.net/test?retryWrites=true

Resources