mock static without #RunWith(PowerMockRunner.class) - java

I have folowing code:
#RunWith(PowerMockRunner.class)
#PrepareForTest({RequestUtils.class, OsgiUtil.class})
#PowerMockIgnore({"*"})
public class MyTest
...
#Test
public somMethod(){
....
mockStatic(RequestUtils.class);
when(RequestUtils.getLocale(request)).thenReturn(locale);
}
}
How to replace this code so that it work without #RunWith(PowerMockRunner.class)?
According the cause described in following link I cannot use #RunWith(PowerMockRunner.class)

Take a look on this discussion: issues while using #RunWith Annotation and powerMock
One of the answers recommends to use PowerMockRule instead of runner. This solution should be good for you.

Related

Change the behavior of a method to use in unit Test in Java

my problem is that my unit test are slow because I'm publishing in a topic in those unit test, I would like to mock or change its behavior in some way. I was thinking in use reflection for this class and change the method behavior but I'm not sure if that is possible.
This is the behavior that I like to mock or change:
TopicCall.builder()
.toTopic(XXXX)
.withAttribute(XXXXXX, XXXXX)
.withAttribute(XXXXX, XXXXXX)
.withAttribute(XXXXX,XXXXX)
.publish();
I would like to do this because publis() is a real invocation and the test is slow and causing some problems in jenkins, because several unit test are publishing at the same time.
The Topic class is a public class with a static builder method which return a class instance, just like the next one:
public static TopicCall builder() {
return new TopicCall();
}
My problem is that I just acceding the method of this class from outside and I'm not sending the class in the constructor as example and I'm not able to mock its behavior, I'm not able to modify the TopicCall class because it is a .class utility from a jar, besides that I'm not able to use PowerMockito or another library, just Mockito, is there any way to achieve that?
Thanks!
Disclaimer: I missed the fact that PowerMock is forbidden for the author, but the answer could be useful for other users with the same problem.
PowerMock
As far as you want to mock a static method, then Mockito is not the solution.
This could be done using PowerMock.
PowerMock uses ClassLoader way for mocking, which could significantly increase tests time to run.
Here is an examle on Baeldung how to mock static methods.
Solution scratch:
#RunWith(PowerMockRunner.class)
#PrepareForTest({ TopicCall.class })
public class Test {
#Test
void test() {
mockStatic(TopicCall.class);
when(TopicCall.builder()).thenReturn(/*value to be returned*/ null);
// the test code...
}
}

Using PowerMockito to mock Path.getParent()

I have been getting the following error:
org.powermock.reflect.exceptions.MethodNotFoundException: No methods matching the name(s) getParent were found in the class hierarchy of class java.lang.Object.
I'm not sure why. I have tried creating some simple code to narrow down the error and don't understand why this mock isn't working.
The code to test:
public void forTest(File xmlFile){
Path p = Paths.get(xmlFile.getAbsolutePath());
p.getParent();
}
The test Code:
#RunWith(PowerMockRunner.class)
#PrepareForTest({XmlFileFunctions.class,Paths.class})
public class XmlFileFunctionsTest {
#InjectMocks
XmlFileFunctions xmlFileFunctionsMock;
#Mock
File xmlFileMock;
#Mock
Path pMock;
#Test
public void myTest(){
when(xmlFileMock.getAbsolutePath()).thenReturn("abc");
PowerMockito.mockStatic(Paths.class);
when(Paths.get(Matchers.anyString())).thenReturn(pMock);
xmlFileFunctionsMock.forTest(xmlFileMock);
verify(pMock).getParent();
}
}
After going down a different solution path, I found the following answer: Mockito and PowerMock MethodNotFoundException being thrown
It seems that changing the version of powermock from 1.6.6 to 1.6.5 fixes this issue.

How do I get an outline specification in Java JUnit?

I'm looking for the ability to nest JUnit tests. I found #RunWith(Enclosed.class), but it only runs one level inclosed and other tests aren't run.
Never mind, I found the answer over here: NitorCreations Nested Runner
This is exactly what I was looking for. It allows JUnit tests to be fully nested.
Because NestedRunner tests did not properly visualize test names in my IntelliJ IDEA I am using HierarchicalContextRunner instead
It provides exactly the same functionality. Just swap them in the #RunWith if you are not happy with how your IDE is showing your tests.
Here is an example of what was wrong:
#RunWith(NestedRunner.class)
public class ATest {
#Test
public void haveARegularTestsInside() {}
public class hasASubClass {
#Test
public void thatHasTests() {}
}
}
looks like this:
Here I expected to have thatHasTests at the last line, but got the whole AClass$hasASubClass.thatHasTests.
change #RunWith to HierarchicalContextRunner and what you get is now this:
Better, isn't it?

Using PowerMock with Cucumber

I've written a JUnit test that uses Mockito and PowerMock to mock some classes. I'm trying to convert it a Cucumber test, but the static PowerMock features don't work.
Extracts of the two relevant Cucumber classes:
Runner
#RunWith(Cucumber.class)
public class JWTValidatorBDDTest {
}
Steps Class
public class JWTValidatorCukeTest {
String tokenValue;
JWTValidator jwtValidator;
MockHttpServletRequest mockRequest;
#Before
public void before() throws IOException {
this.mockRequest = new MockHttpServletRequest();
PowerMockito.mockStatic(JWTAuthConnectionManager.class);
BDDMockito.given(JWTAuthConnectionManager.postToken(anyString(), anyString(), anyString())).willReturn(200);
Mockito.doReturn(200).when(JWTAuthConnectionManager.postToken(anyString(), anyString(), anyString()));
}
#Given("^a JWT token with the value (.*)")
public void a_JWT_token_with_the_value_(String token) {
this.jwtValidator = new JWTValidator("https://test.7uj67hgfh.com/openam", "Authorization", "Bearer");
this.tokenValue = token;
}
Whilst this code works within the JUnit test, it fails here - it enters the JWTAuthConnectionManager.postToken() method that should be mocked and then fails by executing code within there. I've tried adding the lines:
#RunWith(PowerMockRunner.class)
#PrepareForTest(JWTAuthConnectionManager.class)
to both of the above classes (although of course I can't use RunWith in the Runner class as it already has one RunWith annotation), but this doesn't change anything.
How do I get PowerMock to work within Cucumber?
Seems like it is possible now with #PowerMockRunnerDelegate annotation. I use #RunWith(PowerMockRunner.class) and #PowerMockRunnerDelegate(Cucumber.class) and it's working. Taken an advise from here: https://medium.com/#WZNote/how-to-make-spock-and-powermock-work-together-a1889e9c5692
Since version 1.6.0 PowerMock has support for delegating the test execution to another JUnit runner without using a JUnit Rule. This leaves the actual test-execution to another runner of your choice. For example tests can delegate to “SpringJUnit4ClassRunner”, “Parameterized” or the “Enclosed” runner.
There are also options of using #Rule: PowerMockRule rule = new PowerMockRule(); instead of #RunWith(PowerMockRunner.class) (so Runner can be something else) - but the comment by Stefan Birkner suggests that Cucumber runner should support rules to use this and I am not sure if it does (now).
Hope it helps someone.
You can't use the PowerMockRunner because a test can only have one runner (in your case Cucumber). But AFAIK you can use the PowerMockRule instead of the PowerMockRunner.

Running PowerMock with Enclosed class

I have a problem about running PowerMock with #Runwith(Enclosed.class) in pararell.
My test class structure:
#RunWith(PowerMockRunner.class)
#PrepareForTest(UnitBuild.class)
public class ut_QueueBuild{
#Test
public void someTest(){}
public static InnerTestClass{
#Test
public void someInnerTest(){}
}
}
Before using powerMock I just used:
#RunWith(Enclosed.class)
public class unitTestClass {
...
But since I am using PowerMock there is no possibility to use in pararell
#Runwith(PowerMockRunner.class)
and
#Runwith(Enclosed.class)
How can I solve this ?
Thanks a lot !
Actually you can use PowerMockRunnerDelegate and do:
#RunWith(PowerMockRunner.class)
#PowerMockRunnerDelegate(Enclosed.class)
#PrepareForTest(MyStaticClass.class)
public class ut_QueueBuild{
#Test
public void someTest(){}
public static InnerTestClass{
#Test
public void someInnerTest(){}
}
}
This applies also to other runners, like the Parametrized.
JUnit4 only supports one #RunWith annotation, and JUnit4's #RunWith annotation doesn’t accept multiple runners.Reference: project13
Possible duplicate question but here's the answer from this StackOverflow Question #Matthew Farwell
No, you either need to:
use one and create a test base class that does the things you wanted
the other runner to do. separate your test into multiple tests, each
using different runners.

Categories