PowerMock is not intercepting new Instances - java

Hi I´m trying to test some legacy code that uses command patron. I couldn´t make work PowerMock propperly and I tryed to make a simple example to test if it could work.
I think that the problem is that the method whenNew() or expectNew() is not intercepting when in the original code a "new" instance is declared.
Here is the code:
ClassToTest
public class ClassToTest {
public ClassToTest() {
}
public ClassInstance getClassInstance() {
ClassInstance a = new ClassInstance(1);
return a;
}
}
ClassInstance
public class ClassInstance {
private int detector;
public ClassInstance(int detector) {
this.detector = detector;
}
public int getDetector() {
return detector;
}
public void setDetector(int detector) {
this.detector = detector;
}
}
The test
#RunWith(PowerMockRunner.class)
#PrepareForTest({ClassToTestTest.class, ClassInstance.class})
public class ClassToTestTest {
#Test
public void test() throws Exception {
ClassInstance n = new ClassInstance(2);
PowerMockito.whenNew(ClassInstance.class).withAnyArguments().thenReturn(n);
ClassToTest c = Mockito.spy(ClassToTest.class);
System.out.println(c.getClassInstance().getDetector());
}
}
And here is the pom.xml.
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.18.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-core</artifactId>
<version>2.0.9</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>2.0.9</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<version>2.0.9</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-easymock</artifactId>
<version>2.0.9</version>
<scope>test</scope>
</dependency>
So when I run the test, the expected value if PowerMockito intercepts the new instance should be 2 but the console gives me 1...

Related

PowerMock private void method with arguments

I'm looking for a unit test for Controllers using Mockito and PowerMock. Every controller has only private void methods with a single argument and a #Autowired service dependency:
public class ProjectController {
private ProjectServiceImpl service;
#Autowired
public void setInjectedBean(ProjectServiceImpl service) {
this.service = service;
}
private void createProject(String someString) {
// do stuff by calling service.doSomething(someString)
}
}
ProjectServiceImpl is annotated with #Service and has only a public void method with a String as argument. As it is too simple, I didn't bother providing the code.
My last attempt to accomplish that test looks like this:
#RunWith(PowerMockRunner.class)
#ExtendWith(MockitoExtension.class)
#PrepareForTest({ProjectController.class, ProjectServiceImpl.class})
class ProjectControllerTest {
#InjectMocks
private ProjectController controller;
#Mock
private ProjectServiceImplservice;
#Test
void createProject() throws Exception {
controller = PowerMockito.spy(new ProjectController());
PowerMockito.doNothing().when(controller, "createProject", new String(""));
}
}
Question 1: is it possible to make PowerMock work aside of Mockito?
Question 2: using PowerMock, what's the most appropriate way of calling for a private void method with argument?
IMPORTANT: Before marking this post as a duplicate, I personally challenge you finding any content how to do so. It seems like there is just no content showing not only how to make both work together, but make PowerMockito calls for a private void method with one or more arguments.
dependencies used for PowerMock:
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>2.0.9</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-core</artifactId>
<version>2.0.9</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>2.0.9</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<version>2.0.9</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>

Test annotation processor with spring test

I am using junit to test my annotation processor. The test is failing. It seems like never entering the joinpoint, without any exception.
My annotation is like this:
#Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
#Retention(RetentionPolicy.RUNTIME)
public #interface EventListener {
boolean isListening() default true;
boolean isDefaultListener() default true;
Class<SomeListener> subscriber() default None.class;
public static class None implements SomeListener {
... ...
}
}
And the processor like this:
#Aspect
public class ListenerProcessor {
#Pointcut("#annotation(com.xxx.common.event.annotation.EventListener)")
public void sign() {}
#Before("sign()")
public void anAdvice(JoinPoint joinPoint) { ***//this has never executed***
MethodSignature signature = (MethodSignature)joinPoint.getSignature();
Method method = signature.getMethod();
EventListener anno = method.getAnnotation(EventListener.class);
if (anno != null) {
if (anno.isListening()) {
if (anno.isDefaultListener())
doDefault();
else {
Class<SomeListener> clazz = anno.subscriber();
doCustomize(clazz);
}
} else {
... ...
}
}
}
... ...
}
My test is like this:
#RunWith(SpringRunner.class)
#ContextConfiguration(locations = "classpath:applicationContext.xml")
public class EventListenerTest {
#Test
public final void test() {
//given
Long bef = countEvents();
//when
TestEntity1 t1 = appWithDefaultListener();
//then
TestEntity1 t2 = getEntityLike(t1);
Long aft = countEvents();
assertThat(t1).isEqualToComparingFieldByField(t2);
assertThat(aft).isEqualTo(bef+1);
}
#Transactional
#EventListener(isListening=true, isDefaultListener=true) ***//this seems does'nt work***
private TestEntity1 appWithDefaultListener() {
TestEntity1 t1 = new TestEntity1(...);
return myRepository.save(t1);
}
#Transactional(readOnly = true)
private TestEntity1 getEntityLike(TestEntity1 t1) {
TestEntity1 t2 = myRepository.findOne(Example.of(t1));
return t2;
}
}
My applicationContext.xml is like this:
<aop:aspectj-autoproxy proxy-target-class="true">
<aop:include name="eventProcessor"/>
</aop:aspectj-autoproxy>
<context:annotation-config />
<bean id="eventProcessor"
class="com.xxx.common.event.process.EventListenerProcessor"
scope="prototype"/>
And My pom has these dependencies:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.13.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.13</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.13</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.4</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.13.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>2.6.0</version>
</dependency>
What am I missing? Or any thing goes wrong?
Don't define appWithDefaultListener() and getEntityLike() as private methods in your test class.
Instead, you need to define them as non-private methods in another class that you configure as a bean in the test's ApplicationContext. Then have that bean #Autowired into your test class and invoke the methods via that reference so that your aspect is applied.

Mockito mock constructor example

I'm trying to instantiate a mock object with Mockito. I found two examples in the article here, still this article is a very bad example for a newbie like me in Mockito.
Can somebody give me a better example of how it is done with either of the two options?
Simple when doing PowerMockito
public class A {
private final String name;
public A(String name) {
this.name= name;
}
public String sayHello() {
return "Hi " + this.name;
}}
#RunWith(PowerMockRunner.class)
#PrepareForTest(A.class)
public class MockA {
#Test
public void testSayHello throws Throwable {
A a = mock(A.class);
when(a.sayHello()).thenReturn("Hi PowerMockito");
PowerMockito.whenNew(A.class).withArguments(Mockito.anyString()).thenReturn(a);
assertThat(new A("I am mockcked").sayHello(), equalTo("Yes, you are!"));
}
}
Dependencies
<dependencies>
<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-api-mockito</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>{mockito.version}</version>
<scope>test</scope>
</dependency>
</dependencies>

Jersey: Injecting of shared object not working with Jetty

We want to implement a REST-Service on a Jetty, that receives a Heartbeat from multiple Clients and these Heartbeats are stored in a Hashmap to work with them in further functionallities.
Thats how the code looks like at the moment:
The class that should be injected.
public class SharedMemory {
private SharedMemory sharedMemory = null;
private HashMap<String, HeartbeatModel> memory = null;
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
private final Lock readLock = lock.readLock();
private final Lock writeLock = lock.writeLock();
public SharedMemory(){
memory = new HashMap<String, HeartbeatModel>();
}
...
}
The binder class:
public class SharedMemoryBinder extends AbstractBinder{
#Override
protected void configure() {
bind(new SharedMemory()).to(SharedMemory.class);
}
}
The feature class:
public class SharedMemoryFeature implements Feature{
#Override
public boolean configure(FeatureContext context) {
context.register(new SharedMemoryBinder());
return true;
}
}
The service class
#Path("/HeartbeatService")
public class GCEHeartbeatService {
#Inject
private SharedMemory sharedMemory;
#POST
#Path("/postHeartbeat")
#Consumes(MediaType.APPLICATION_JSON)
public Response postHeartbeat(Heartbeat heartbeat){
sharedMemory.storeToMemory(heartbeat);
return Response.ok().build();
}
...
}
The application class:
#ApplicationPath("/")
public class Application extends javax.ws.rs.core.Application {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> classes = new HashSet<>();
classes.add(GCEHeartbeatService.class);
classes.add(SharedMemoryFeature.class);
return classes;
}
}
These are the used dependencies:
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>2.17</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.17</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.4.1</version>
</dependency>
<dependency>
<groupId>de.hszg</groupId>
<artifactId>common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.bundles</groupId>
<artifactId>jaxrs-ri</artifactId>
<version>2.13</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.5.3</version>
</dependency>
</dependencies>
So with this configuration, i always get a 415 unsupported media type exception when i post a heartbeat to the postHeartbeat service, even with another media type.
"...i always get a 415 unsupported media type exception when i post"
This doesn't seem like a problem related to your DI configuration. It looks like you just need to register the JSON provider. With this particular provider
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.5.3</version>
</dependency>
If you override the registration of resources/provider through classpath scanning (which you have done, simply by overriding getClasses() and returning a non-empty set, then the provider will not be registered.
You can simply register it yourself.
classes.add(JacksonJsonProvider.class);
-- or --
classes.add(JacksonJaxbJsonProvider.class);
If you look in the jar, you will also see an ExceptionMapper you may want to register.
Alternatively, you can use this dependency
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.17</version>
</dependency>
which wraps the above dependency in a auto-discoverable feature, and registers, the provider and the ExceptionMapper. With this dependency, you won't need to register anything. If for some weird reason it isn't register, you can just add it yourself
classes.add(JacksonFeature.class);
As an aside, if portability is not an issue, I would use the ResourceConfig class (which extends Application) instead. It's much easier to work with.
#ApplicationPath("/")
public class AppConfig extends ResourceConfig {
public AppConfig() {
packages("scan.packages.for.resource.and.provider");
register(ResourceOrProvider.class);
register(new MyAppBinder());
}
}
See the ResourceConfig API

powermock+easymock+testng for testing a final class

Using these dependencies in my pom.xml
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-easymock</artifactId>
<version>1.5.5</version>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-test-easymock-testng</artifactId>
<version>1.5.5</version>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-core</artifactId>
<version>1.5.5</version>
</dependency>
This is my code, where Dispute is a class of type final.
#PrepareForTest(Dispute.class)
public void testProcessChargebackUpdates() {
final List<BraintreeGateway> credentials = new LinkedList<BraintreeGateway>();
credentials.add(credential);
// Dispute dispute = control.createMock(Dispute.class);
Dispute dispute = PowerMock.createMock(Dispute.class);
}
Gives cannot instantiate final class.
First of you need these dependencies :
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-test-easymock-testng</artifactId>
<version>1.5.5</version>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-testng</artifactId>
<version>1.4.9</version>
</dependency><dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-core</artifactId>
<version>1.5.5</version>
</dependency>
Then you need this in your class, #Prepare annotation with the final class to be mocked, as
well as the getObjectFactory method to be defined in the class.
#PrepareForTest(Dispute.class)
public void testProcessChargebackUpdates() {
#ObjectFactory
public IObjectFactory getObjectFactory() {
return new PowerMockObjectFactory();
}
}

Categories