org.powermock.api.mockito.ClassNotPreparedException in Static class mocking - java

I am writing a unit test to mock a static method in the verticle but getting ClassNotPreparedException always. I think that its only possible to mock this way if only the class is static, but i have non static class. What am i missing?
I have tried various solutions like using #rule or #PowerMockIgnore
//myVerticleTest.java
package com.blabla.me.verticles;
import static com.google.common.truth.Truth.assertThat;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import io.vertx.core.Vertx;
import io.vertx.junit5.VertxTestContext;
import io.vulpx.VulpxTestBase;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.junit.runner.RunWith;
import com.blabla.me.verticles.AdditionalInformationCardVerticle;
import org.powermock.modules.junit4.rule.PowerMockRule;
import org.junit.Rule;
import com.blabla.me.verticles.st;
#RunWith(PowerMockRunner.class)
#PrepareForTest({ st.class })
#PowerMockIgnore({"org.mockito.*"})
public class myVerticleTest extends VulpxTestBase {
#Rule public PowerMockRule rule = new PowerMockRule();
private Vertx vertx;
private AdditionalInformationCardVerticle dummy;
#BeforeEach
#PrepareForTest({ st.class })
public void setUp(VertxTestContext testContext) throws Exception {
vertx = Vertx.vertx();
try {
PowerMockito.mockStatic(st.class);
PowerMockito.when(st.createClient()).thenReturn("kk");
//deploying verticle
dummy = new AdditionalInformationCardVerticle();
vertx.deployVerticle(dummy, testContext.completing());
} catch (Exception e) {
System.out.println("heyyy eroorrr : " + e);
}
}
#Test
#PrepareForTest({ st.class })
public void justnormaltest() {
cla ownclass = new cla();
String k = ownclass.createfromclass();
assertThat("kk").isEqualTo(k);
}
}
// st.java
public class st {
public static String createClient() {
return "kk";
}
}
// cla.java
public class cla {
public String createfromclass() {
return st.createClient();
}
}
I expect it to run the assertion but i always get below excpetion:
"org.powermock.api.mockito.ClassNotPreparedException:
The class com.sap.me.verticles.st 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. "

Here:
#PrepareForTest({ st.class })
That one goes to exactly one place: in front of your test class public class myVerticleTest.
And hint: instead of adding more and more "things" to not working code: pick any good documentation, and try to follow that to the last ; in the example code (instead of assuming that adding more and more things here or there would help).
One good starting point: the official documentation on static mocking.
And of course, the usual caveat: consider not learning about PowerMock in the first place. Instead focus on writing "easy to test" code. Far too often, people think PowerMock(ito) is the answer to their problem. When their problem in reality is their inability to write "easy to test" production code.

Related

Mocking org.springframework.web.reactive.function.client.WebClient.ResponseSpec#onStatus input parameters

Considering the following code:
public Mono<Void> doStuff() {
return this.requestStuff()
.onStatus(HttpStatus::is5xxServerError,
clientResponse -> {
aMethodIWouldLikeToTest(clientResponse);
return Mono.error(new MyCustomException("First error I would like to test"));
})
.onStatus(HttpStatus::is4xxClientError,
clientResponse -> {
aMethodIWouldLikeToTest(clientResponse);
return Mono.error(new MyCustomException("Second error I would like to test"));
})
.bodyToMono(String.class)
.flatMap(x -> anotherMethodIManagedToTest(x)))
}
My first goal was to test anotherMethodIManagedToTest(x) that was achieved using:
import org.springframework.web.reactive.function.client.WebClient;
...
#Mock
private WebClient.ResponseSpec responseSpec;
private String desiredInputParam = "There is another black spot on the sun today!";
...
#Test
public void allGood_anotherMethodIManagedToTest_success {
...
ClassUnderTest classUnderTest = new classUnderTest()
ClassUnderTest classUnderTestSpy = spy(classUnderTestSpy);
doReturn(responseSpec).when(classUnderTestSpy).requestStuff();
when(responseSpec.onStatus(any(), any())).thenReturn(responseSpec);
when(responseSpec.bodyToMono(String.class)).thenReturn(Mono.just(desiredInputParam));
Mono<Void> result = classUnderTestSpy.doStuff();
// Bunch of assertions for anotherMethodIManagedToTest(String desiredInputParam) performed with success ...
}
Now I would like to create additional tests to test the event of a 5xxServerError and the event of a 4xxClientError but I am having a hard time figuring how to:
Mock the response of HttpStatus::is5xxServerError
Mock the response of HttpStatus::is4xxServerError
Mock the clientResponse in order to test aMethodIWouldLikeToTest(org.springframework.web.reactive.function.client.ClientResponse clientResponse)
Any suggestions on how to perform these actions?
Please note that I cannot really use any PowerMock alternatives (still interested if this is the only way to acheive my goal) all answers with standard Mockito are preferred.
I am sorry about my late response.
It is possible to use mockito for your test case:
you need to get the HttpStatus to check it in the onStatus method
so first create an abstract class (to avoid implementing all the methods) that implements WebClient.ResponseSpec
you can create a mock from this class instead of ResponseSpec
I added 2 methods in this class:
abstract class CustomMinimalForTestResponseSpec implements WebClient.ResponseSpec {
public abstract HttpStatus getStatus();
public WebClient.ResponseSpec onStatus(Predicate<HttpStatus> statusPredicate, Function<ClientResponse, Mono<? extends Throwable>> exceptionFunction) {
if (statusPredicate.test(this.getStatus())) exceptionFunction.apply(ClientResponse.create(HttpStatus.OK).build()).block();
return this;
}
}
the getStatus will be used to set the HttpStatus:
when(responseSpecMock.getStatus()).thenReturn(HttpStatus.INTERNAL_SERVER_ERROR);
and for the onStatus, you can call the real method:
when(responseSpecMock.onStatus(any(Predicate.class),any(Function.class)))
.thenCallRealMethod();
This is the test class:
package com.example.test;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.HttpStatus;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import java.util.function.Function;
import java.util.function.Predicate;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
#ExtendWith(MockitoExtension.class)
public class ExperimentalWebClientTest {
#Mock
private WebClient webClientMock;
#InjectMocks
private ExperimentalWebClient experimentalWebClient;
#Mock
private WebClient.RequestHeadersUriSpec requestHeadersUriSpecMock;
#Mock
private WebClient.RequestHeadersSpec requestHeadersSpecMock;
#Mock
private CustomMinimalForTestResponseSpec responseSpecMock;
#Test
void shouldFailsWhenHttpStatus5xx() {
//given
when(webClientMock.get()).thenReturn(requestHeadersUriSpecMock);
when(requestHeadersUriSpecMock.uri(any(Function.class)))
.thenReturn(requestHeadersSpecMock);
when(requestHeadersSpecMock.retrieve()).thenReturn(responseSpecMock);
when(responseSpecMock.getStatus()).thenReturn(HttpStatus.INTERNAL_SERVER_ERROR);
when(responseSpecMock.onStatus(any(Predicate.class), any(Function.class))).thenCallRealMethod();
//when + Then
assertThrows(MyCustomException.class,
() -> experimentalWebClient.doStuff(),
"call fails with Internal Server Error") ;
}
abstract class CustomMinimalForTestResponseSpec implements WebClient.ResponseSpec {
public abstract HttpStatus getStatus();
public WebClient.ResponseSpec onStatus(Predicate<HttpStatus> statusPredicate, Function<ClientResponse, Mono<? extends Throwable>> exceptionFunction) {
if (statusPredicate.test(this.getStatus())) exceptionFunction.apply(ClientResponse.create(HttpStatus.OK).build()).block();
return this;
}
}
}
I think the answer to my question is that Mockito is not the right tool to test such a thing. Using wiremock seems like the convenient approach
When I test using mainly the following libraries :
import com.github.tomakehurst.wiremock.client.WireMock;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.reactive.server.WebTestClient;
I managed to get the job done.
If you are facing a similar issue, I recommend you take a look at https://www.sudoinit5.com/post/spring-boot-testing-consumer/, the provided examples are similar to what I have done to accomplish my tests.
However, I am still interested if anyone knows a way to accomplish the question with Mockito.

Is it possible to mock the result of a private method and at the same time obtain coverage in sonar or jacoco?

I need to test a method which calls another private method, the problem is not to try to mock the result that the private method returns, but to do so not to obtain the coverage of jacoco or sonar. I tested with Powermock, with EasyMock but when using a spy, when use an spy the test is not covered by sonar or jacoco. The private method and the public method that make the call are at the same class.
Situation to test:
public class ClassOne {
private Object methodOne () {
.....
return object;
}
private Object mehodTwo () {
return Object name = mehtodOne ();
}
}
Test example:
package foo.bar;
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest(VlcPlayerMinimal.class)
public class VlcPlayerMinimalTest {
#Test
public void getVlcRcStatusTest() {
VlcPlayerMinimal vlcPlayerSpy = PowerMockito.spy(new VlcPlayerMinimal());
try {
PowerMockito.doReturn("{status: stopped, id: 2}").when(vlcPlayerSpy, "executeGetRequest", Mockito.any(), Mockito.any());
String vlcRcStatus = vlcPlayerSpy.getVlcRcStatus();
System.out.println(vlcRcStatus);
} catch (Exception e) {
e.printStackTrace();
fail("Unexpected exception thrown.");
}
}
}
No, it's not possible. Pick one or the other.
What would such "coverage" even prove? You are not actually covering it. Code coverage is a metric to help you identify spots that are not well tested, not one that you should try to trick into appearing higher than it really is.

Exception while using PowerMockito with static method

I want to mock a static method using PowerMockito,
public class DepedencyService {
public static int getImportantValue() {
return -4;
}
}
public class Component {
public int componentMethod() {
return DepedencyService.getImportantValue();
}
}
but it is giving me an exception.
import static org.testng.Assert.assertEquals;
import org.easymock.EasyMock;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest(DepedencyService.class)
public class ComponentTest {
#Test
public void testComponentMethod() {
Component c = new Component();
PowerMockito.mockStatic(DepedencyService.class);
EasyMock.expect(DepedencyService.getImportantValue()).andReturn(1);
assertEquals(1, c.componentMethod());
}
}
The exception :-
java.lang.IllegalStateException: no last call on a mock available at
org.easymock.EasyMock.getControlForLastCall(EasyMock.java:520) at
org.easymock.EasyMock.expect(EasyMock.java:498)
Can anyone please help me? Why is this failing? I am new to PowerMockito and does not know what to do here!
Your main problem is that you're writing STUPID code (like most of us did at the beginning) where you rather should write SOLID code.
Using Powermock is just a surrender to this bad design.
Yes, classes having only static methods are called utility classes.
But you should get over this misconception that classes providing common behavior should have (only) static methods.
As a rule of thumb there should be only one non private static method in your entire program, and this is main().
You appear to be mixing mocking frameworks.
You need to properly arrange the static dependencies before exercising the test
Since PowerMockito is used to mock the static class then you should use Mockito to arrange the expected behavior
For example
#RunWith(PowerMockRunner.class)
#PrepareForTest(DepedencyService.class)
public class ComponentTest {
#Test
public void testComponentMethod() {
//Arrange
int expected = 1;
PowerMockito.mockStatic(DepedencyService.class);
Mockito.when(DepedencyService.getImportantValue()).thenReturn(expected);
Component subject = new Component();
//Act
int actual = subject.componentMethod();
//Assert
assertEquals(expected, actual);
}
}
That said, I would advise not having your code tightly coupled to static dependencies. It makes for difficult to test code.

Mocking getResource in static block with PowerMock

How to mock getResourceAsStream in the static block?
I think it is untestable.
I reviewed SO and cannot find the answer. The closes-SO-post-here does not address the issue as the call to getResourceAsAStream in the post is not from a static block.
I tried PowerMock, and run into number of limitations. First if I want to mock SomeProperties.class.getResourceAsStream - the static block will execute, as I will need to refer to the class itself. I can suppress static block to prevent doing so, but this will prevent me from getting the static block to execute at all. The solution would be to postpone the execution of the static block until after someProperties.class.getResourceAsStream is mocked.
I do not think it is possible though.
It seems that this code is purely untestable;
Any other ideas?
Here is the code [and a link to GITHUB]:
package com.sopowermock1;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class SomeProperties {
private static Properties props = new Properties();
static {
InputStream is = SomeProperties.class.getResourceAsStream("/some.properties");
try {
props.load(is);
System.out.println("Properties.props.keySet() = " + props.keySet());
} catch (IOException e) {
// How test this branch???
System.out.println("Yes. We got here.");
throw new RuntimeException(e);
}
}
private SomeProperties() {}; // to makes life even harder...
public static String getVersion() {
return props.getProperty("version");
}
}
And here is the test GITHUB Link
package com.sopowermock1;
import java.io.InputStream;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import com.sopowermock1.SomeProperties;
#RunWith(PowerMockRunner.class)
#PrepareForTest(SomeProperties.class)
// This will prevent running static block completely:
// #SuppressStaticInitializationFor("com.sopowermock1.SomeProperties")
public class SomePropertiesTest {
#Mock
private static InputStream streamMock;
#Before
public void setUp() {
MockitoAnnotations.initMocks(SomeProperties.class);
System.out.println("test setUp");
}
#Test(expected = RuntimeException.class)
public void testStaticBlock() {
PowerMockito.mockStatic(SomeProperties.class); // this will mock all static methods (unwanted as we want to call getVersion)
// This will cause static block to be called.
PowerMockito.when(SomeProperties.class.getResourceAsStream("/some.properties")).thenReturn(streamMock);
SomeProperties.getVersion();
}
}
Any ideas?. Full GITHUB source is here.
as mention in How to mock getResourceAsStream method using PowerMockito and JUnit?, use Extract Delegate , then mock the delegate class such as XXStreamFetcher, and then you can test it.

How do I mock static methods in a class with easymock?

Suppose I have a class like so:
public class StaticDude{
public static Object getGroove() {
// ... some complex logic which returns an object
};
}
How do I mock the static method call using easy mock? StaticDude.getGroove().
I am using easy mock 3.0
Not sure how to with pure EasyMock, but consider using the PowerMock extensions to EasyMock.
It has a lot of cool functions for doing just what you need -
https://github.com/jayway/powermock/wiki/MockStatic
Easymock is a testing framework for "for interfaces (and objects through the class extension)" so you can mock a class without an interface. Consider creating an interfaced object with an accessor for your static class and then mock that acessor instead.
EDIT: Btw, I wouldn't recommend doing static classes. It is better to have everything interfaced if you are doing TDD.
Just in Case PowerMock is unavailable for any reason:
You could move the static call to a method, override this method in the instantiation of the tested class in the test class, create a local interface in the test class and use its method in the overidden method:
private interface IMocker
{
boolean doSomething();
}
IMocker imocker = EasyMock.createMock(IMocker.class);
...
#Override
void doSomething()
{
imocker.doSomething();
}
...
EasyMock.expect(imocker.doSomething()).andReturn(true);
Generally speaking, it is not possible to mock a static method without using some sort of accessor, which seems to defeat the purpose of using a static method. It can be quite frustrating.
There is one tool that I know of called "TypeMock Isolator" which uses some sort of Satanic Magic to mock static methods, but that tool is quite expensive.
The problem is, I know of no way to override a static method. You can't declare it virtual. you can't include it in an interface.
Sorry to be a negative nelly.
Adding an exemple on how to implements static mock along regular mock of injected classes with EasyMock / PowerMock, since the linked exemple only shows static mock.
And with the PowerMockRunner the #Mock services are not wired on the #TestSubject service to test.
Let say we have a service we want to test, ServiceOne :
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
#Service
public class ServiceOne {
#Autowired
private ServiceTwo serviceTwo;
public String methodToTest() {
String returnServ2 = serviceTwo.methodToMock();
return ServiceUtils.addPlus(returnServ2);
}
}
Which calls another service that we will want to mock, ServiceTwo :
import org.springframework.stereotype.Service;
#Service
public class ServiceTwo {
public String methodToMock() {
return "ServiceTwoReturn";
}
}
And which calls a final class static method, ServiceUtils :
public final class ServiceUtils {
public static String addPlus(String pParam) {
return "+" + pParam;
}
}
When calling ServiceOne.methodToTest() we get "+ServiceTwoReturn" as a return.
Junit Test with EasyMock, mocking only the injected ServiceTwo Spring service :
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.junit.Assert.assertEquals;
import org.easymock.EasyMockRunner;
import org.easymock.Mock;
import org.easymock.TestSubject;
import org.junit.Test;
import org.junit.runner.RunWith;
#RunWith(EasyMockRunner.class)
public class ExempleTest {
#TestSubject
private ServiceOne serviceToTest = new ServiceOne();
#Mock
private ServiceTwo serviceMocked;
#Test
public void testMethodToTest() {
String mockedReturn = "return2";
expect(serviceMocked.methodToMock()).andReturn(mockedReturn);
replay(serviceMocked);
String result = serviceToTest.methodToTest();
verify(serviceMocked);
assertEquals("+" + mockedReturn, result);
}
}
Junit Test with EasyMock & PowerMock, mocking the injected ServiceTwo Spring service but also the final class and its Static method :
import static org.easymock.EasyMock.expect;
import static org.junit.Assert.assertEquals;
import static org.powermock.api.easymock.PowerMock.createMock;
import static org.powermock.api.easymock.PowerMock.mockStatic;
import static org.powermock.reflect.Whitebox.setInternalState;
import org.easymock.Mock;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest(ServiceUtils.class)
public class ExempleTest {
private ServiceOne serviceToTest;
private ServiceTwo serviceMocked;
#Before
public void setUp() {
serviceToTest = new ServiceOne();
serviceMocked = createMock(ServiceTwo.class);
// This will wire the serviced mocked into the service to test
setInternalState(serviceToTest, serviceMocked);
mockStatic(ServiceUtils.class);
}
#Test
public void testMethodToTest() {
String mockedReturn = "return2";
String mockedStaticReturn = "returnStatic";
expect(serviceMocked.methodToMock()).andReturn(mockedReturn);
expect(ServiceUtils.addPlus(mockedReturn)).andReturn(mockedStaticReturn);
PowerMock.replayAll();
String result = serviceToTest.methodToTest();
PowerMock.verifyAll();
assertEquals(mockedStaticReturn, result);
}
}

Categories