1
0
mirror of synced 2026-05-22 21:33:16 +00:00

Remove Powermock

Powermock does not support JUnit5 yet, so we need to remove it
to support JUnit 5. Additionally, maintaining additional libraries
adds extra work for the team.

Mockito now supports final classes and static method mocking. This
commit replaces Powermock with mockito-inline.

Closes gh-6025
This commit is contained in:
Rob Winch
2021-07-07 09:11:53 -05:00
parent e30b45c6fb
commit 14240b2559
43 changed files with 300 additions and 286 deletions
+2 -1
View File
@@ -20,9 +20,10 @@ dependencies {
optional 'org.springframework:spring-tx'
optional 'org.jetbrains.kotlinx:kotlinx-coroutines-reactor'
testImplementation powerMock2Dependencies
testImplementation 'commons-collections:commons-collections'
testImplementation 'io.projectreactor:reactor-test'
testImplementation 'org.mockito:mockito-core'
testImplementation 'org.mockito:mockito-inline'
testImplementation 'org.skyscreamer:jsonassert'
testImplementation 'org.slf4j:jcl-over-slf4j'
testImplementation 'org.springframework:spring-test'
@@ -24,9 +24,8 @@ import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.mockito.MockedStatic;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
@@ -41,8 +40,7 @@ import static org.mockito.ArgumentMatchers.eq;
* @since 3.2
*
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({ DelegatingSecurityContextRunnable.class, DelegatingSecurityContextCallable.class })
@RunWith(MockitoJUnitRunner.class)
public abstract class AbstractDelegatingSecurityContextTestSupport {
@Mock
@@ -66,22 +64,26 @@ public abstract class AbstractDelegatingSecurityContextTestSupport {
@Mock
protected Runnable wrappedRunnable;
public final void explicitSecurityContextPowermockSetup() throws Exception {
PowerMockito.spy(DelegatingSecurityContextCallable.class);
PowerMockito.doReturn(this.wrappedCallable).when(DelegatingSecurityContextCallable.class, "create",
eq(this.callable), this.securityContextCaptor.capture());
PowerMockito.spy(DelegatingSecurityContextRunnable.class);
PowerMockito.doReturn(this.wrappedRunnable).when(DelegatingSecurityContextRunnable.class, "create",
eq(this.runnable), this.securityContextCaptor.capture());
@Mock
protected MockedStatic<DelegatingSecurityContextCallable> delegatingSecurityContextCallable;
@Mock
protected MockedStatic<DelegatingSecurityContextRunnable> delegatingSecurityContextRunnable;
public final void explicitSecurityContextSetup() throws Exception {
this.delegatingSecurityContextCallable.when(
() -> DelegatingSecurityContextCallable.create(eq(this.callable), this.securityContextCaptor.capture()))
.thenReturn(this.wrappedCallable);
this.delegatingSecurityContextRunnable.when(
() -> DelegatingSecurityContextRunnable.create(eq(this.runnable), this.securityContextCaptor.capture()))
.thenReturn(this.wrappedRunnable);
}
public final void currentSecurityContextPowermockSetup() throws Exception {
PowerMockito.spy(DelegatingSecurityContextCallable.class);
PowerMockito.doReturn(this.wrappedCallable).when(DelegatingSecurityContextCallable.class, "create",
this.callable, null);
PowerMockito.spy(DelegatingSecurityContextRunnable.class);
PowerMockito.doReturn(this.wrappedRunnable).when(DelegatingSecurityContextRunnable.class, "create",
this.runnable, null);
public final void currentSecurityContextSetup() throws Exception {
this.delegatingSecurityContextCallable.when(() -> DelegatingSecurityContextCallable.create(this.callable, null))
.thenReturn(this.wrappedCallable);
this.delegatingSecurityContextRunnable.when(() -> DelegatingSecurityContextRunnable.create(this.runnable, null))
.thenReturn(this.wrappedRunnable);
}
@Before
@@ -33,7 +33,7 @@ public class CurrentDelegatingSecurityContextExecutorServiceTests
@Before
public void setUp() throws Exception {
super.currentSecurityContextPowermockSetup();
super.currentSecurityContextSetup();
}
@Override
@@ -32,7 +32,7 @@ public class CurrentDelegatingSecurityContextExecutorTests extends AbstractDeleg
@Before
public void setUp() throws Exception {
super.currentSecurityContextPowermockSetup();
super.currentSecurityContextSetup();
}
@Override
@@ -33,7 +33,7 @@ public class CurrentDelegatingSecurityContextScheduledExecutorServiceTests
@Before
public void setUp() throws Exception {
this.currentSecurityContextPowermockSetup();
this.currentSecurityContextSetup();
}
@Override
@@ -33,7 +33,7 @@ public class DelegatingSecurityContextSupportTests extends AbstractDelegatingSec
@Test
public void wrapCallable() throws Exception {
explicitSecurityContextPowermockSetup();
explicitSecurityContextSetup();
this.support = new ConcreteDelegatingSecurityContextSupport(this.securityContext);
assertThat(this.support.wrap(this.callable)).isSameAs(this.wrappedCallable);
assertThat(this.securityContextCaptor.getValue()).isSameAs(this.securityContext);
@@ -41,14 +41,14 @@ public class DelegatingSecurityContextSupportTests extends AbstractDelegatingSec
@Test
public void wrapCallableNullSecurityContext() throws Exception {
currentSecurityContextPowermockSetup();
currentSecurityContextSetup();
this.support = new ConcreteDelegatingSecurityContextSupport(null);
assertThat(this.support.wrap(this.callable)).isSameAs(this.wrappedCallable);
}
@Test
public void wrapRunnable() throws Exception {
explicitSecurityContextPowermockSetup();
explicitSecurityContextSetup();
this.support = new ConcreteDelegatingSecurityContextSupport(this.securityContext);
assertThat(this.support.wrap(this.runnable)).isSameAs(this.wrappedRunnable);
assertThat(this.securityContextCaptor.getValue()).isSameAs(this.securityContext);
@@ -56,7 +56,7 @@ public class DelegatingSecurityContextSupportTests extends AbstractDelegatingSec
@Test
public void wrapRunnableNullSecurityContext() throws Exception {
currentSecurityContextPowermockSetup();
currentSecurityContextSetup();
this.support = new ConcreteDelegatingSecurityContextSupport(null);
assertThat(this.support.wrap(this.runnable)).isSameAs(this.wrappedRunnable);
}
@@ -33,7 +33,7 @@ public class ExplicitDelegatingSecurityContextExecutorServiceTests
@Before
public void setUp() throws Exception {
super.explicitSecurityContextPowermockSetup();
super.explicitSecurityContextSetup();
}
@Override
@@ -32,7 +32,7 @@ public class ExplicitDelegatingSecurityContextExecutorTests extends AbstractDele
@Before
public void setUp() throws Exception {
super.explicitSecurityContextPowermockSetup();
super.explicitSecurityContextSetup();
}
@Override
@@ -33,7 +33,7 @@ public class ExplicitDelegatingSecurityContextScheduledExecutorServiceTests
@Before
public void setUp() throws Exception {
this.explicitSecurityContextPowermockSetup();
this.explicitSecurityContextSetup();
}
@Override
@@ -16,18 +16,22 @@
package org.springframework.security.core;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.Whitebox;
import org.mockito.MockedStatic;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.core.SpringVersion;
import org.springframework.util.ReflectionUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
@@ -42,21 +46,29 @@ import static org.mockito.Mockito.verifyZeroInteractions;
* @author Luke Taylor
* @author Rob Winch
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({ SpringSecurityCoreVersion.class, SpringVersion.class })
@RunWith(MockitoJUnitRunner.class)
public class SpringSecurityCoreVersionTests {
@Mock
private Log logger;
@Mock(answer = Answers.CALLS_REAL_METHODS)
private MockedStatic<SpringVersion> springVersion;
@Mock(answer = Answers.CALLS_REAL_METHODS)
private MockedStatic<SpringSecurityCoreVersion> springSecurityCoreVersion;
@Before
public void setup() {
Whitebox.setInternalState(SpringSecurityCoreVersion.class, this.logger);
public void setup() throws Exception {
Field logger = ReflectionUtils.findField(SpringSecurityCoreVersion.class, "logger");
StaticFinalReflectionUtils.setField(logger, this.logger);
}
@After
public void cleanup() throws Exception {
System.clearProperty(getDisableChecksProperty());
Field logger = ReflectionUtils.findField(SpringSecurityCoreVersion.class, "logger");
StaticFinalReflectionUtils.setField(logger, LogFactory.getLog(SpringSecurityCoreVersion.class));
}
@Test
@@ -79,40 +91,34 @@ public class SpringSecurityCoreVersionTests {
@Test
public void noLoggingIfVersionsAreEqual() throws Exception {
String version = "1";
PowerMockito.spy(SpringSecurityCoreVersion.class);
PowerMockito.spy(SpringVersion.class);
PowerMockito.doReturn(version).when(SpringSecurityCoreVersion.class, "getVersion");
PowerMockito.doReturn(version).when(SpringVersion.class, "getVersion");
expectSpringSecurityVersionThenReturn(version);
expectSpringVersionThenReturn(version);
performChecks();
verifyZeroInteractions(this.logger);
}
@Test
public void noLoggingIfSpringVersionNull() throws Exception {
PowerMockito.spy(SpringSecurityCoreVersion.class);
PowerMockito.spy(SpringVersion.class);
PowerMockito.doReturn("1").when(SpringSecurityCoreVersion.class, "getVersion");
PowerMockito.doReturn(null).when(SpringVersion.class, "getVersion");
String version = "1";
expectSpringSecurityVersionThenReturn(version);
expectSpringVersionThenReturn(null);
performChecks();
verifyZeroInteractions(this.logger);
}
@Test
public void warnIfSpringVersionTooSmall() throws Exception {
PowerMockito.spy(SpringSecurityCoreVersion.class);
PowerMockito.spy(SpringVersion.class);
PowerMockito.doReturn("3").when(SpringSecurityCoreVersion.class, "getVersion");
PowerMockito.doReturn("2").when(SpringVersion.class, "getVersion");
expectSpringSecurityVersionThenReturn("3");
expectSpringVersionThenReturn("2");
performChecks();
verify(this.logger, times(1)).warn(any());
}
@Test
public void noWarnIfSpringVersionLarger() throws Exception {
PowerMockito.spy(SpringSecurityCoreVersion.class);
PowerMockito.spy(SpringVersion.class);
PowerMockito.doReturn("4.0.0.RELEASE").when(SpringSecurityCoreVersion.class, "getVersion");
PowerMockito.doReturn("4.0.0.RELEASE").when(SpringVersion.class, "getVersion");
String version = "4.0.0.RELEASE";
expectSpringSecurityVersionThenReturn(version);
expectSpringVersionThenReturn(version);
performChecks();
verify(this.logger, never()).warn(any());
}
@@ -121,20 +127,16 @@ public class SpringSecurityCoreVersionTests {
@Test
public void noWarnIfSpringPatchVersionDoubleDigits() throws Exception {
String minSpringVersion = "3.2.8.RELEASE";
PowerMockito.spy(SpringSecurityCoreVersion.class);
PowerMockito.spy(SpringVersion.class);
PowerMockito.doReturn("3.2.0.RELEASE").when(SpringSecurityCoreVersion.class, "getVersion");
PowerMockito.doReturn("3.2.10.RELEASE").when(SpringVersion.class, "getVersion");
expectSpringSecurityVersionThenReturn("3.2.0.RELEASE");
expectSpringVersionThenReturn("3.2.10.RELEASE");
performChecks(minSpringVersion);
verify(this.logger, never()).warn(any());
}
@Test
public void noLoggingIfPropertySet() throws Exception {
PowerMockito.spy(SpringSecurityCoreVersion.class);
PowerMockito.spy(SpringVersion.class);
PowerMockito.doReturn("3").when(SpringSecurityCoreVersion.class, "getVersion");
PowerMockito.doReturn("2").when(SpringVersion.class, "getVersion");
expectSpringSecurityVersionThenReturn("3");
expectSpringVersionThenReturn("2");
System.setProperty(getDisableChecksProperty(), Boolean.TRUE.toString());
performChecks();
verifyZeroInteractions(this.logger);
@@ -144,12 +146,25 @@ public class SpringSecurityCoreVersionTests {
return SpringSecurityCoreVersion.class.getName().concat(".DISABLE_CHECKS");
}
private void performChecks() throws Exception {
Whitebox.invokeMethod(SpringSecurityCoreVersion.class, "performVersionChecks");
private void performChecks() {
Method method = ReflectionUtils.findMethod(SpringSecurityCoreVersion.class, "performVersionChecks");
ReflectionUtils.makeAccessible(method);
ReflectionUtils.invokeMethod(method, null);
}
private void performChecks(String minSpringVersion) throws Exception {
Whitebox.invokeMethod(SpringSecurityCoreVersion.class, "performVersionChecks", minSpringVersion);
private void performChecks(String minSpringVersion) {
Method method = ReflectionUtils.findMethod(SpringSecurityCoreVersion.class, "performVersionChecks",
String.class);
ReflectionUtils.makeAccessible(method);
ReflectionUtils.invokeMethod(method, null, minSpringVersion);
}
private void expectSpringSecurityVersionThenReturn(String version) {
this.springSecurityCoreVersion.when(SpringSecurityCoreVersion::getVersion).thenReturn(version);
}
private void expectSpringVersionThenReturn(String version) {
this.springVersion.when(SpringVersion::getVersion).thenReturn(version);
}
}
@@ -0,0 +1,115 @@
/*
* Copyright 2008 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
*
* https://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.springframework.security.core;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.security.PrivilegedAction;
import sun.misc.Unsafe;
import org.springframework.objenesis.instantiator.util.UnsafeUtils;
/**
* Used for setting static variables even if they are private static final.
*
* The code in this class has been adopted from Powermock's <a href=
* "https://github.com/noushadali/powermock/blob/powermock-1.5.4/reflect/src/main/java/org/powermock/reflect/internal/WhiteboxImpl.java#L326">WhiteboxImpl</a>.
*
* @author Rob Winch
*/
final class StaticFinalReflectionUtils {
/**
* Used to support setting static fields that are final using Java's Unsafe. If the
* field is not static final, use
* {@link org.springframework.test.util.ReflectionTestUtils}.
* @param field the field to set
* @param newValue the new value
*/
static void setField(final Field field, final Object newValue) {
try {
field.setAccessible(true);
int fieldModifiersMask = field.getModifiers();
boolean isFinalModifierPresent = (fieldModifiersMask & Modifier.FINAL) == Modifier.FINAL;
if (isFinalModifierPresent) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
try {
Unsafe unsafe = UnsafeUtils.getUnsafe();
long offset = unsafe.staticFieldOffset(field);
Object base = unsafe.staticFieldBase(field);
setFieldUsingUnsafe(base, field.getType(), offset, newValue, unsafe);
return null;
}
catch (Throwable thrown) {
throw new RuntimeException(thrown);
}
}
});
}
else {
field.set(null, newValue);
}
}
catch (SecurityException ex) {
throw new RuntimeException(ex);
}
catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
}
catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
}
private static void setFieldUsingUnsafe(Object base, Class type, long offset, Object newValue, Unsafe unsafe) {
if (type == Integer.TYPE) {
unsafe.putInt(base, offset, ((Integer) newValue));
}
else if (type == Short.TYPE) {
unsafe.putShort(base, offset, ((Short) newValue));
}
else if (type == Long.TYPE) {
unsafe.putLong(base, offset, ((Long) newValue));
}
else if (type == Byte.TYPE) {
unsafe.putByte(base, offset, ((Byte) newValue));
}
else if (type == Boolean.TYPE) {
unsafe.putBoolean(base, offset, ((Boolean) newValue));
}
else if (type == Float.TYPE) {
unsafe.putFloat(base, offset, ((Float) newValue));
}
else if (type == Double.TYPE) {
unsafe.putDouble(base, offset, ((Double) newValue));
}
else if (type == Character.TYPE) {
unsafe.putChar(base, offset, ((Character) newValue));
}
else {
unsafe.putObject(base, offset, newValue);
}
}
private StaticFinalReflectionUtils() {
}
}
@@ -33,7 +33,7 @@ public class CurrentSecurityContextSchedulingTaskExecutorTests
@Before
public void setUp() throws Exception {
currentSecurityContextPowermockSetup();
currentSecurityContextSetup();
}
@Override
@@ -33,7 +33,7 @@ public class ExplicitSecurityContextSchedulingTaskExecutorTests
@Before
public void setUp() throws Exception {
explicitSecurityContextPowermockSetup();
explicitSecurityContextSetup();
}
@Override
@@ -33,7 +33,7 @@ public class CurrentDelegatingSecurityContextAsyncTaskExecutorTests
@Before
public void setUp() throws Exception {
currentSecurityContextPowermockSetup();
currentSecurityContextSetup();
}
@Override
@@ -41,7 +41,7 @@ public class CurrentDelegatingSecurityContextTaskExecutorTests extends AbstractD
@Before
public void setUp() throws Exception {
currentSecurityContextPowermockSetup();
currentSecurityContextSetup();
}
@Override
@@ -33,7 +33,7 @@ public class ExplicitDelegatingSecurityContextAsyncTaskExecutorTests
@Before
public void setUp() throws Exception {
explicitSecurityContextPowermockSetup();
explicitSecurityContextSetup();
}
@Override
@@ -41,7 +41,7 @@ public class ExplicitDelegatingSecurityContextTaskExecutorTests extends Abstract
@Before
public void setUp() throws Exception {
explicitSecurityContextPowermockSetup();
explicitSecurityContextSetup();
}
@Override