I'm wondering is it possible to make TestNG show in it's report something like nested tests or test steps.
The thing is that I have pretty big integration test cases and it would be nice if I could decouple it on some steps, say, with something like allure's #Step annotation.
For now the test case is shown as one huge separate entry in intellij IDEA report with a lot of logs which is very difficult to go through and analyze.
You can use createNode method of ExtentTest class. it will creating node under main test.
I've never tried to use Inner TestNG classes but that might be possible and I do believe IntelliJ would render the nested view. You could make a simple little project to try it out. There is a guy who seems to have tried inner classes here: http://makeseleniumeasy.com/2018/05/13/testng-tutorials-12-how-to-run-inner-testng-class-from-testng-xml/ . Let me know if it works. Won't know if IntelliJ renders the nesting until you try.
Bonus: If that works, would be interesting to execute your TestNG using Gradle testng plugin and see if HTML report also renders the nesting.
Inner classes can be used to form groups. For one level of nesting the inner classes must be made public.
Try the following:
public class foo {
public class bar1 {
#Test
public void test11() {System.out.println("test11");}
#Test
public void test12() {System.out.println("test12");}
}
public class bar2 {
#Test
public void test21() {System.out.println("test21");}
#Test
public void test22() {System.out.println("test22");}
}
}
JUnit does have #Nested to group them and you can use the shortcut cmd+R etc. to run them, especially if you have lots of test cases
For TestNG, either split them into different (inner) classes, or use structure view in IntelliJ (https://www.jetbrains.com/help/idea/viewing-structure-of-a-source-file.html)
Right-click all those tests that you want to run
Now you can use groups feature of TestNG E.g.:
class RecordsAccessorTest {
#BeforeMethod(groups = "NewRecordGroup")
public void setUp() {
// some set up for only new record creation is tested
}
#Test(groups = "NewRecordGroup")
public void testNewRecordCreation_happyPath() {...}
#Test(groups = "NewRecordGroup")
public void testNewRecordCreation_errorPath() {...}
#Test
public void someOtherTestNotInGroup() {...}
}
I have a test which verifies a static method was called with certain arguments
#PowerMockIgnore({"javax.management.*"})
#RunWith(PowerMockRunner.class)
#PrepareForTest({MyUtil.class})
#TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class MyTest {
#Test
public void Test() {
PowerMockito.mockStatic(MyUtil.class);
when(MyUtil.doStaticMethod(any(), any())).thenReturn("value");
// do test
...
verifyStatic(MyUtil.class, times(1));
MyUtil.doStaticMethod("a", "b");
}
}
This works fine if the method is called once with arguments "a" and "b", however if I change verification to either times(2) or "aa", "b" instead of getting a test failure error I get
org.mockito.exceptions.misusing.NotAMockException: Argument should be a mock, but is: class java.lang.Class
at org.powermock.core.MockGateway.doMethodCall(MockGateway.java:182)
at org.powermock.core.MockGateway.doMethodCall(MockGateway.java:164)
at org.powermock.core.MockGateway.methodCall(MockGateway.java:141)
at com.mycompany.project.MyUtil.doStaticMethod(S3ServiceUtil.java)
at ...
I am using powermock 1.7.4 and mockito 2.8.9 and have mock-maker-inline configured for final class instrumentation. I haven't been able to find anything, any ideas? Thank you!
i have a problem which occurs when using NetBeans 8.2 and JUnit.
Considering the following example:
Unit Test:
private MyClass myClass = new MyClass();
#Test
public void testSomething() {
myClass.testMethod();
}
// OTHER TEST EXISTING BUT THESE ARE TAGGED WITH #IGNORE
If I am using the following production code:
MyClass:
public class MyClass {
public void testMethod() {
System.out.print("test");
}
}
The "Unit test output" in NetBeans displays something like:
test
Testcase: testSomethingOther(mypackage.MyClassTest):SKIPPED
Testcase: testSomethingOther2(mypackage.MyClassTest):SKIPPED
-- other tests which are ignored / failed --
But I only want NetBeans to display my own "print" statements, and not some Test details.
If i am using the "println" function, it works as as planned (no test details are written to output console).
What is the problem here?
You're using the annotation #Test which implies that you're probably using JUnit, TestNG or another Testing framework. If you don't want to see your framework's prints either check if there's a configuration setting / flag that you can pass that turns it off or stop using it and find another way to run your tests.
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;
I am trying to just run a simple test case. I have the following method.
public static void run(String[] args) throws Throwable {
CommandLineArguments opts = CommandLineOptionProcessor.getOpts(args);
}
I will continue to build this method / test case as I go. However I just wanted to make sure a simple test case worked first. So I wrote the following test.
#Test
public void testRun() {
String[] args = {"--arg1", "value", "--arg2", "value2"};
mockStatic(CommandLineOptionProcessor.class);
expect(CommandLineOptionProcessor.getOpts(args));
EasyMock.replay(CommandLineOptionProcessor.class);
}
After that I get the following error:
java.lang.IllegalStateException: no last call on a mock available
I read some of the other posts on StackOverflow but their solution seemed to be that they were using PowerMock with Mockito. I am using Powermock and Easymock, so that should not be the problem.
I followed Rene's advice and added the following to the top of my class.
#PrepareForTest(CommandLineOptionProcessor.class)
#RunWith(PowerMockRunner.class)
public class DataAssemblerTest {
I fixed the previous error. But now I have this error.
java.lang.IllegalArgumentException: Not a mock: java.lang.Class
at org.easymock.internal.ClassExtensionHelper.getControl(ClassExtensionHelper.java:61)
at org.easymock.EasyMock.getControl(EasyMock.java:2172)
at org.easymock.EasyMock.replay(EasyMock.java:2074)
.
.
.
Any ideas on what could be causing this would be great.
Did you annotate the test class with #RunWith(PowerMockRunner.class) and #PrepareForTest(CommandLineOptionProcessor.class)?
#RunWith(PowerMockRunner.class)
#PrepareForTest(CommandLineOptionProcessor.class)
public class TestClass {
#Test
public void testRun(){
You need the #PrepareForTest(CommandLineOptionProcessor.class) at the test class level. See the Powermock doc:
Use the #PrepareForTest(ClassThatContainsStaticMethod.class) annotation at the class-level of the test case.
Also ensure that the required libraries are on the test classpath.
In your case the javassist library is missing. Put it on the classpath. Maybe some other libs are also missing... we will see.
If you get
java.lang.IllegalArgumentException: Not a mock: java.lang.Class
then you are using EasyMock.replay(), but you must use PowerMock.replay()
EasyMock.expectLastCall()
or
EasyMock.expectLastCall().anyTimes()
or
EasyMock.expectLastCall().andAnswer(..)
is not present in your code, must be after the method you want to test
this is in case your test method is a void method.
otherwise you can use :
expect(CommandLineOptionProcessor.getOpts(args)).andReturn(object);
also please add this to you test class :
#ObjectFactory
public IObjectFactory getObjectFactory() {
return new org.powermock.modules.testng.PowerMockObjectFactory( );
}