I don't have the newest version of TestNG, and I have option to add #Test on constructor, java docs
#Target({METHOD, TYPE, CONSTRUCTOR})
public #interface Test {
I didn't find any clue on usage in docs or searching online
#Test Marks a class or a method as part of the test.
When/Why #Test can be define on constructor? is it for internal purposes only?
I saw that CONSTRUCTOR was removed in latest TestNG version, but I didn't find why.
See issue "Remove irrelevant "targets" for TestNG annotations": The target CONSTRUCTOR had no functionality in older versions, because constructors were not seen as test methods. That's why the target was removed later.
I am using DependOnGroups parameter in #test annotation.the code looks like,
#Test(groups={"datacompare"},dependsOnGroups = {"AzkabanFlow"})
Now the requirement is we need to run the test only for the group datacompare which is done by specifying the maven parameter,
clean test site -DtestGroup=datacompare
Since the above group has dependency with the group azkban flow, i am getting the error
[ERROR] DependencyMap::Method "DataValidationTestSuite.data_Comparison(java.lang.reflect.Method)[pri:0, instance:com.kohls.test.automation.framework.testsuite.DataValidationTestSuite#1608e1a]" depends on nonexistent group "AzkabanFlow"
Can someone suggest me a way to run the test for datacompare without removing the parameter DependOnGroups and also not calling the particular group mentioned in dependOnGroup parameter in maven parameter for test run.
You might want to change your #Test annotation to something like below
#Test(groups={"datacompare"},dependsOnGroups = {"AzkabanFlow"}, ignoreMissingDependencies=true)
This would cause TestNG to ignore missing dependencies and hopefully it should solve your problem as well.
Javadocs for the same can be referred here.
I have the following simple code. I have a class (TestClass) and I want to test "someMethod". There is an external static method which is called by my "someMethod".
I want to Powermock that static method to return me some dummy object.
I have the #PrepareForTest(ExternalClass.class) in the begining, but when I execute it gives the error:
The class ExternalClass not prepared for test.
To prepare this class, add class to the '#PrepareForTest' annotation.
In case if you don't use this annotation, add the annotation on class or method level.
Please help me to point out what is wrong with the way I have used #PrepareForTest
#RunWith(PowerMockRunner.class)
#PrepareForTest(ExternalClass.class)
public class xyzTest {
#Mock
private RestTemplate restTemplate;
#Mock
private TestClass testClass;
#BeforeClass
private void setUpBeforeClass() {
MockitoAnnotations.initMocks(this);
}
#Test
public void testSuccessCase() {
Boolean mockResponse = true;
ResponseEntity<Boolean> response = new ResponseEntity<Boolean>(mockResponse, HttpStatus.OK);
SomeClass someClass = new SomeClass("test", "1.0.0", "someUrl", "someMetaData");
PowerMockito.mockStatic(ExternalClass.class);
Mockito.when(restTemplate.postForEntity(any(String.class), any(String.class), eq(Boolean.class))).thenReturn(response);
Mockito.when(ExternalClass.getSomeClass(any(String.class))).thenReturn(someClass);
Boolean result = testClass.someMethod("test");
Assert.isTrue(result);
Mockito.verify(restTemplate, times(1)).postForObject(any(String.class), any(String.class), any());
}
}
Make sure you add #RunWith(PowerMockRunner.class) to the top of your class as well.
::edit:: two years later...
Don't ever use PowerMockito, you shouldn't need to.
If you do need to, you have most likely broken the SOLID principles and your design is wrong.
Fix your design instead.
As with the last answer, my problem was also mixing the Test annotation from TestNG instead of Junit Test.
import org.junit.Test; // works
import org.testng.annotations.Test // did not work
Very abstruse error and I spent more than 5 hrs debugging :(
For those trying to get this working with Junit 5, If your using the powermock-module-junit4 beta release which claims to be compatible with 4+, the library will still not recognize:
import org.junit.jupiter.api.Test;
and it will throw a:
org.powermock.api.mockito.ClassNotPreparedException
when #PrepareForTest is applied on the class you want to static mock. If you want to use PowerMock, you will have to go back to Junit 4 or create a MockWrapper for your static method at this time.
PowerMock 2.0: Github Roadmap
While the top-rated answer here is correct without a doubt, this does not answer the question of why is that needed; or, for example, why the same thing would not work with adding #RunWith(MockitoJUnitRunner.class).
The thing is PowerMockRunner uses instrumentation API under the hood, via
javassist library, this allows to alter the classes, like remove final or mock static (non-compile time constants).
In the process of modifying (instrumenting) a certain class, they add an interface to that, called PowerMockModified. It is a marker interface that denotes that a certain byte-code instrumentation took place. Later in the code, they simply check if the class that you use in #PrepareForTest was actually instrumented in some way or not, via such a method:
private boolean isModifiedByPowerMock() {
return PowerMockModified.class.isAssignableFrom(this.type);
}
In turns out that PowerMockRunner does some instrumentation, while MockitoJUnitRunner does not; thus the error you get.
I had the same error, resolved this by adding
#Rule
public PowerMockRule rule = new PowerMockRule();
inside the test class.
If above answers don't work try extends PowerMockTestCase. This trick worked for me.
Example:
public class xyzTest extends PowerMockTestCase
check if import org.junit.Test; package has imported and not that api jupiter one.
I had the same error but resolved it. My problem was that I included powermock-module-junit4 but included my test annotation from TestNG instead of Junit.
I had the same error. I was using TestNG to run the tests. I had to use the following method to fix the above issue.
#ObjectFactory
public IObjectFactory getObjectFactory() {
return new PowerMockObjectFactory();
}
For testNG there are 2 options as follows :
Using ObjectFactory as below:
#ObjectFactory
public IObjectFactory getObjectFactory() {
return new PowerMockObjectFactory();
}
Test class extending extends org.powermock.modules.testng.PowerMockTestCase
My gradle was using Junit 5.
test {
useJUnitPlatform()
}
I was able to debug this. By having breakpoints in PowerMockRunner methods.
It was not invoked. Moreover JUnit 5 is not supported with PowerMockito.
Looks like JUnit5 runs without #ExtendWith.
Make sure you are using powermock2. I had this problem when I was using powermock.
Use
import org.powermock2.api.mockito.PowerMockito;
Hi I need to write Junit tests for an Android project but it has JNI methods as it uses webkit.Is there any way I can test those android methods(I dont want to test JNI methods).
Its like:
public void androidMethod(){
//some android code
nativeInit(); //how do I mock such methods?
//some code again
}
I have tried powermock,easymock,roboelectric but wasnt successful.Please help me.
I yesterday found I could solve this with Mockito (I didn't try powermock or easymock). Assuming your class is class C, my solution is:
C c=spy(new C);
doNothing().when(c).nativeInit();
c.androidMethod()
verify(c).nativeInit();
This does, of course, require that nativeInit is visible to the test.
Similar Problem
I had the same problem event though I was already using mockito in JUnit tests under src/test. Once I added tests under src/androidTest I started having issues, including this crash:
Mockito cannot mock/spy because :
- final class
And after making the class open, manually, I still got crashes in the JNI layer as it tried to load the *.so library (which wouldn't happen if mocks were working properly).
Working Solution
Instead, what I had to do was open the class for testing purposes using Kotlin's all-open plugin. The process is also explained well in this recent medium post but it boils down to the following four simple changes that are also modeled in one of the architecture components sample apps:
1. Make these additions to build.gradle:
buildscript {
dependencies {
classpath "org.jetbrains.kotlin:kotlin-allopen:${versions.kotlin}"
}
}
apply plugin: "kotlin-allopen"
allOpen {
// marker for classes that we want to be able to extend in debug builds
annotation 'com.your.package.name.OpenClass'
}
2. Add the corresponding annotations in the debug flavor. For example: app/src/debug/java/com/your/package/name/OpenForTesting.kt
package com.your.package.name
#Target(AnnotationTarget.ANNOTATION_CLASS)
annotation class OpenClass
#OpenClass
#Target(AnnotationTarget.CLASS)
annotation class OpenForTesting
3. Add the corresponding annotation in the release flavor. For example: app/src/release/java/com/your/package/name/OpenForTesting.kt
package com.your.package.name
#Target(AnnotationTarget.CLASS)
annotation class OpenForTesting
4. Add the #OpenForTesting annotation to the class that needs to be mocked
package com.your.package.name
#OpenForTesting
class JniClassOfVictory {
...
external fun nativeInit()
...
companion object {
init {
System.loadLibrary("victoryeveryday")
}
}
}
The result is a flexible way to mark classes as open without actually making them open in release builds. Of course, this is because the #OpenForTesting annotation that we created in release is not marked with #OpenClass but the same annotation in debug is marked with #OpenClass. In build.gradle we designated that annotation as the signal to the kotlin-allopen plugin. So any class annotated with #OpenForTesting will be made open at compile-time but only on Debug builds.
I would like to do something like:
#RunWith(Categories.class)
#Categories.IncludeCategory(Small.class)
#Categories.ExcludeCategory({Manual.class, NonFunctional.class})
#Suite.SuiteClasses(AllTests.class)
public class SmallTests {
}
but ExcludeCategories accepts only one class, not an array of classes.
This will be supported in JUnit 4.12 version, see https://github.com/junit-team/junit/blob/master/src/main/java/org/junit/experimental/categories/Categories.java
It looks like runtime-suite may provide another workaround/solution.
There's a JUnit 4 feature request for this:
https://github.com/junit-team/junit/issues/146
This link also suggests a workaround:
There is a not-so-beatiful workaround. You can get multiple includes or excludes
if you create an inheritance hierarchy of suites and exclude one category on
each level.