Skip to content

Commit

Permalink
Add support Mockito-2.0. Repacked cglib.
Browse files Browse the repository at this point in the history
Fix powermock#613
Also added new Maven profile: mockito2.
  • Loading branch information
thekingn0thing committed Feb 21, 2016
1 parent bac70b8 commit 8bf2e60
Show file tree
Hide file tree
Showing 284 changed files with 43,386 additions and 77 deletions.
38 changes: 38 additions & 0 deletions api/mockito2/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.powermock</groupId>
<artifactId>powermock-api</artifactId>
<version>1.6.5-SNAPSHOT</version>
</parent>

<artifactId>powermock-api-mockito2</artifactId>
<name>${project.artifactId}</name>

<description>
PowerMock API for Mockito.
</description>

<dependencies>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-support</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/*
* Copyright 2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.powermock.api.extension.listener;

import org.mockito.Answers;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.MockSettings;
import org.mockito.MockitoAnnotations.Mock;
import org.mockito.exceptions.base.MockitoException;
import org.mockito.internal.configuration.InjectingAnnotationEngine;
import org.mockito.internal.util.reflection.GenericMaster;
import org.powermock.api.mockito.internal.configuration.PowerMockitoInjectingAnnotationEngine;
import org.powermock.core.spi.listener.AnnotationEnablerListener;
import org.powermock.core.spi.support.AbstractPowerMockTestListenerBase;
import org.powermock.reflect.Whitebox;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Set;

import static org.mockito.Mockito.withSettings;
import static org.powermock.api.mockito.PowerMockito.mock;

/**
* Before each test method all fields annotated with {@link Mock},
* {@link org.mockito.Mock} or {@link Mock} have mock objects created for them
* and injected to the fields. It will also delegate to a special implementation
* of the {@link InjectingAnnotationEngine} in Mockito which inject's spies,
* captors etc.
* <p/>
* It will only inject to fields that haven't been set before (i.e that are
* <code>null</code>).
*/
@SuppressWarnings("deprecation")
public class AnnotationEnabler extends AbstractPowerMockTestListenerBase implements AnnotationEnablerListener {

@Override
public void beforeTestMethod(Object testInstance, Method method, Object[] arguments) throws Exception {
standardInject(testInstance);
injectSpiesAndInjectToSetters(testInstance);
injectCaptor(testInstance);
}

private void injectSpiesAndInjectToSetters(Object testInstance) {
new PowerMockitoInjectingAnnotationEngine().process(testInstance.getClass(), testInstance);
}

private void injectCaptor(Object testInstance) throws Exception {
Set<Field> fieldsAnnotatedWithCaptor = Whitebox.getFieldsAnnotatedWith(testInstance, Captor.class);
for (Field field : fieldsAnnotatedWithCaptor) {
final Object captor = processAnnotationOn(field.getAnnotation(Captor.class), field);
field.set(testInstance, captor);
}
}

private void standardInject(Object testInstance) throws IllegalAccessException {
Set<Field> fields = Whitebox.getFieldsAnnotatedWith(testInstance, getMockAnnotations());
for (Field field : fields) {
if (field.get(testInstance) != null) {
continue;
}
final Class<?> type = field.getType();
if (field.isAnnotationPresent(org.powermock.core.classloader.annotations.Mock.class)) {
org.powermock.core.classloader.annotations.Mock annotation = field
.getAnnotation(org.powermock.core.classloader.annotations.Mock.class);
final String[] value = annotation.value();
if (value.length != 1 || !"".equals(value[0])) {
System.err
.println("PowerMockito deprecation: Use PowerMockito.spy(..) for partial mocking instead. A standard mock will be created instead.");
}
}

if (field.isAnnotationPresent(org.mockito.Mock.class)) {
org.mockito.Mock mockAnnotation = field.getAnnotation(org.mockito.Mock.class);
MockSettings mockSettings = withSettings();
Answers answers = mockAnnotation.answer();
if (answers != null) {
mockSettings.defaultAnswer(answers.get());
}

Class<?>[] extraInterfaces = mockAnnotation.extraInterfaces();
if (extraInterfaces != null && extraInterfaces.length > 0) {
mockSettings.extraInterfaces(extraInterfaces);
}

String name = mockAnnotation.name();
if (name != null && name.length() > 0) {
mockSettings.name(name);
}

field.set(testInstance, mock(type, mockSettings));
} else {
field.set(testInstance, mock(type));
}
}
}

@SuppressWarnings("unchecked")
@Override
public Class<? extends Annotation>[] getMockAnnotations() {
return new Class[]{org.mockito.Mock.class, Mock.class, org.powermock.core.classloader.annotations.Mock.class};
}

private Object processAnnotationOn(Captor annotation, Field field) {
Class<?> type = field.getType();
if (!ArgumentCaptor.class.isAssignableFrom(type)) {
throw new MockitoException("@Captor field must be of the type ArgumentCaptor.\n" + "Field: '"
+ field.getName() + "' has wrong type\n"
+ "For info how to use @Captor annotations see examples in javadoc for MockitoAnnotations class.");
}
Class cls = new GenericMaster().getGenericType(field);
return ArgumentCaptor.forClass(cls);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright 2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.powermock.api.extension.proxyframework;

import org.powermock.api.mockito.repackaged.cglib.proxy.Enhancer;
import org.powermock.api.mockito.repackaged.cglib.proxy.Factory;
import org.powermock.reflect.spi.ProxyFramework;

/**
* CGLib proxy framework setup.
*/
public class ProxyFrameworkImpl implements ProxyFramework {

/**
* {@inheritDoc}
*/
@Override
public Class<?> getUnproxiedType(Class<?> type) {
Class<?> currentType = type;
while (isProxy(currentType)) {
for (Class<?> i : currentType.getInterfaces()) {
if (!i.getName().equals(Factory.class.getName())) {
return i;
}
}
currentType = currentType.getSuperclass();
}
return currentType;
}

/**
* {@inheritDoc}
*/
@Override
public boolean isProxy(Class<?> type) {
if (type == null) {
return false;
}
return type.getName().contains("$$EnhancerByMockitoWithCGLIB$$") || Enhancer.isEnhanced(type);
}
}
Loading

0 comments on commit 8bf2e60

Please sign in to comment.