Skip to content

Commit

Permalink
Merge branch 'main' into bugfix/mockito#2602-makeSureConstructorInjec…
Browse files Browse the repository at this point in the history
…tionIsUsedIfValidConstructorExists
  • Loading branch information
TimvdLippe committed Jun 12, 2023
2 parents e54d95e + 5cccfda commit 1556f76
Show file tree
Hide file tree
Showing 64 changed files with 1,037 additions and 67 deletions.
15 changes: 8 additions & 7 deletions build.gradle
Expand Up @@ -7,22 +7,22 @@ buildscript {

dependencies {
classpath 'gradle.plugin.com.hierynomus.gradle.plugins:license-gradle-plugin:0.16.1'
classpath 'net.ltgt.gradle:gradle-errorprone-plugin:3.0.1'
classpath 'net.ltgt.gradle:gradle-errorprone-plugin:3.1.0'

classpath "io.github.gradle-nexus:publish-plugin:1.1.0"
classpath "io.github.gradle-nexus:publish-plugin:1.3.0"
classpath 'org.shipkit:shipkit-changelog:1.2.0'
classpath 'org.shipkit:shipkit-auto-version:1.2.2'

classpath 'com.google.googlejavaformat:google-java-format:1.15.0'
classpath 'com.google.googlejavaformat:google-java-format:1.17.0'
classpath 'com.android.tools.build:gradle:7.3.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.10"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.22"
}
}

plugins {
id 'com.diffplug.spotless' version '6.15.0'
id 'com.diffplug.spotless' version '6.19.0'
id 'eclipse'
id 'com.github.ben-manes.versions' version '0.46.0'
id 'com.github.ben-manes.versions' version '0.47.0'
id 'biz.aQute.bnd.builder' version '6.4.0'
id 'ru.vyarus.animalsniffer' version '1.7.0'
}
Expand Down Expand Up @@ -123,9 +123,10 @@ spotless {
licenseHeaderFile rootProject.file('config/spotless/spotless.header')

custom 'google-java-format', { source ->
com.google.googlejavaformat.java.JavaFormatterOptions options = new com.google.googlejavaformat.java.JavaFormatterOptions.Builder()
com.google.googlejavaformat.java.JavaFormatterOptions options = new com.google.googlejavaformat.java.AutoValue_JavaFormatterOptions.Builder()
.style(com.google.googlejavaformat.java.JavaFormatterOptions.Style.AOSP)
.formatJavadoc(false)
.reorderModifiers(true)
.build()
com.google.googlejavaformat.java.Formatter formatter = new com.google.googlejavaformat.java.Formatter(options)
return formatter.formatSource(source)
Expand Down
16 changes: 8 additions & 8 deletions gradle/dependencies.gradle
Expand Up @@ -4,13 +4,13 @@ ext {

def versions = [:]

versions.bytebuddy = '1.14.0'
versions.junitJupiter = '5.9.2'
versions.errorprone = '2.18.0'
versions.bytebuddy = '1.14.5'
versions.junitJupiter = '5.9.3'
versions.errorprone = '2.19.1'

libraries.junit4 = 'junit:junit:4.13.2'
libraries.junitJupiterApi = "org.junit.jupiter:junit-jupiter-api:${versions.junitJupiter}"
libraries.junitPlatformLauncher = 'org.junit.platform:junit-platform-launcher:1.9.2'
libraries.junitPlatformLauncher = 'org.junit.platform:junit-platform-launcher:1.9.3'
libraries.junitJupiterEngine = "org.junit.jupiter:junit-jupiter-engine:${versions.junitJupiter}"
libraries.junitVintageEngine = "org.junit.vintage:junit-vintage-engine:${versions.junitJupiter}"
libraries.assertj = 'org.assertj:assertj-core:3.24.2'
Expand All @@ -24,17 +24,17 @@ libraries.bytebuddyandroid = "net.bytebuddy:byte-buddy-android:${versions.bytebu
libraries.errorprone = "com.google.errorprone:error_prone_core:${versions.errorprone}"
libraries.errorproneTestApi = "com.google.errorprone:error_prone_test_helpers:${versions.errorprone}"

libraries.autoservice = "com.google.auto.service:auto-service:1.0.1"
libraries.autoservice = "com.google.auto.service:auto-service:1.1.0"

libraries.objenesis = 'org.objenesis:objenesis:3.3'

libraries.osgi = 'org.osgi:osgi.core:8.0.0'
libraries.equinox = 'org.eclipse.platform:org.eclipse.osgi:3.18.200'
libraries.equinox = 'org.eclipse.platform:org.eclipse.osgi:3.18.300'
libraries.bndGradle = 'biz.aQute.bnd:biz.aQute.bnd.gradle:6.4.0'

libraries.groovy = 'org.codehaus.groovy:groovy:3.0.15'
libraries.groovy = 'org.codehaus.groovy:groovy:3.0.17'

def kotlinVersion = '1.8.10'
def kotlinVersion = '1.8.22'
libraries.kotlin = [
version: kotlinVersion,

Expand Down
2 changes: 1 addition & 1 deletion settings.gradle.kts
Expand Up @@ -3,7 +3,7 @@ plugins {
}

include("subclass",
"inline",
"inlineTest",
"proxy",
"extTest",
"groovyTest",
Expand Down
42 changes: 39 additions & 3 deletions src/main/java/org/mockito/ArgumentMatchers.java
Expand Up @@ -14,6 +14,7 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.regex.Pattern;

import org.mockito.internal.matchers.Any;
Expand Down Expand Up @@ -114,7 +115,7 @@
public class ArgumentMatchers {

/**
* Matches <strong>anything</strong>, including nulls and varargs.
* Matches <strong>anything</strong>, including nulls.
*
* <p>
* See examples in javadoc for {@link ArgumentMatchers} class
Expand All @@ -124,7 +125,8 @@ public class ArgumentMatchers {
* <strong>Notes : </strong><br/>
* <ul>
* <li>For primitive types use {@link #anyChar()} family or {@link #isA(Class)} or {@link #any(Class)}.</li>
* <li>Since mockito 2.1.0 {@link #any(Class)} is not anymore an alias of this method.</li>
* <li>Since Mockito 2.1.0 {@link #any(Class)} is not anymore an alias of this method.</li>
* <li>Since Mockito 5.0.0 this no longer matches varargs. Use {@link #any(Class)} instead.</li>
* </ul>
* </p>
*
Expand Down Expand Up @@ -161,7 +163,8 @@ public static <T> T any() {
* <ul>
* <li>For primitive types use {@link #anyChar()} family.</li>
* <li>Since Mockito 2.1.0 this method will perform a type check thus <code>null</code> values are not authorized.</li>
* <li>Since mockito 2.1.0 {@link #any()} is no longer an alias of this method.</li>
* <li>Since Mockito 2.1.0 {@link #any()} is no longer an alias of this method.</li>
* <li>Since Mockito 5.0.0 this method can match varargs if the array type is specified, for example <code>any(String[].class)</code>.</li>
* </ul>
* </p>
*
Expand Down Expand Up @@ -912,6 +915,39 @@ public static <T> T argThat(ArgumentMatcher<T> matcher) {
return null;
}

/**
* Allows creating custom argument matchers where matching is considered successful when the consumer given by parameter does not throw an exception.
* <p>
* Typically used with {@link Mockito#verify(Object)} to execute assertions on parameters passed to the verified method invocation.
*
* @param consumer executes assertions on the verified argument
* @return <code>null</code>.
*/
public static <T> T assertArg(Consumer<T> consumer) {
return argThat(
argument -> {
consumer.accept(argument);
return true;
});
}

/**
* Allows creating custom argument matchers where matching is considered successful when the consumer given by parameter does not throw an exception.
* Consumer is allowed to throw exception other than RuntimeException
* <p>
* Typically used with {@link Mockito#verify(Object)} to execute assertions on parameters passed to the verified method invocation.
*
* @param consumer executes assertions on the verified argument
* @return <code>null</code>.
*/
public static <T> T assertArg(ThrowingConsumer<T> consumer) {
return argThat(
argument -> {
consumer.accept(argument);
return true;
});
}

/**
* Allows creating custom <code>char</code> argument matchers.
* <p>
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/org/mockito/Mock.java
Expand Up @@ -132,6 +132,13 @@
*/
String mockMaker() default "";

/**
* Mock will not attempt to preserve all annotation metadata, see {@link MockSettings#withoutAnnotations()}.
*
* @since 5.3.0
*/
boolean withoutAnnotations() default false;

enum Strictness {

/**
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/org/mockito/MockMakers.java
Expand Up @@ -23,12 +23,14 @@ public final class MockMakers {
* @see <a href="Mockito.html#39">Mocking final types, enums and final methods</a>
*/
public static final String INLINE = "mock-maker-inline";

/**
* Proxy mock maker which avoids code generation, but can only mock interfaces.
*
* @see <a href="Mockito.html#50">Avoiding code generation when restricting mocks to interfaces</a>
*/
public static final String PROXY = "mock-maker-proxy";

/**
* Subclass mock maker which mocks types by creating subclasses.
* This is the first built-in mock maker which has been provided by Mockito.
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/org/mockito/MockSettings.java
Expand Up @@ -5,6 +5,7 @@
package org.mockito;

import java.io.Serializable;
import java.lang.reflect.Type;

import org.mockito.exceptions.misusing.PotentialStubbingProblem;
import org.mockito.exceptions.misusing.UnnecessaryStubbingException;
Expand Down Expand Up @@ -403,4 +404,11 @@ public interface MockSettings extends Serializable {
* @since 4.8.0
*/
MockSettings mockMaker(String mockMaker);

/**
* Specifies the generic type of the mock, preserving the information lost to Java type erasure.
* @param genericTypeToMock
* @return
*/
MockSettings genericTypeToMock(Type genericTypeToMock);
}
38 changes: 28 additions & 10 deletions src/main/java/org/mockito/Mockito.java
Expand Up @@ -10,6 +10,7 @@
import org.mockito.internal.creation.MockSettingsImpl;
import org.mockito.internal.framework.DefaultMockitoFramework;
import org.mockito.internal.session.DefaultMockitoSessionBuilder;
import org.mockito.internal.util.MockUtil;
import org.mockito.internal.verification.VerificationModeFactory;
import org.mockito.invocation.Invocation;
import org.mockito.invocation.InvocationFactory;
Expand Down Expand Up @@ -39,6 +40,7 @@
import org.mockito.verification.VerificationMode;
import org.mockito.verification.VerificationWithTimeout;

import java.util.function.Consumer;
import java.util.function.Function;

/**
Expand Down Expand Up @@ -160,7 +162,8 @@
* }
* </code></pre>
*
* Be aware that this artifact may be abolished when the inline mock making feature is integrated into the default mock maker.
* Be aware that starting from 5.0.0 the <a href="#39">inline mock maker</a> became the default mock maker and this
* artifact may be abolished in future versions.
*
* <p>
* For more information about inline mock making, see <a href="#39">section 39</a>.
Expand Down Expand Up @@ -1327,23 +1330,22 @@
*
* <h3 id="39">39. <a class="meaningful_link" href="#Mocking_Final" name="Mocking_Final">Mocking final types, enums and final methods</a> (Since 2.1.0)</h3>
*
* Mockito now offers an {@link Incubating}, optional support for mocking final classes and methods.
* Mockito now offers support for mocking final classes and methods by default.
* This is a fantastic improvement that demonstrates Mockito's everlasting quest for improving testing experience.
* Our ambition is that Mockito "just works" with final classes and methods.
* Previously they were considered <em>unmockable</em>, preventing the user from mocking.
* We already started discussing how to make this feature enabled by default.
* Currently, the feature is still optional as we wait for more feedback from the community.
* Since 5.0.0, this feature is enabled by default.
*
* <p>
* This alternative mock maker which uses
* a combination of both Java instrumentation API and sub-classing rather than creating a new class to represent
* a mock. This way, it becomes possible to mock final types and methods.
*
* <p>
* This mock maker is <strong>turned off by default</strong> because it is based on completely different mocking mechanism
* that requires more feedback from the community. It can be activated explicitly by the mockito extension mechanism,
* just create in the classpath a file <code>/mockito-extensions/org.mockito.plugins.MockMaker</code>
* containing the value <code>mock-maker-inline</code>.
* In versions preceding 5.0.0, this mock maker is <strong>turned off by default</strong> because it is based on
* completely different mocking mechanism that required more feedback from the community. It can be activated
* explicitly by the mockito extension mechanism, just create in the classpath a file
* <code>/mockito-extensions/org.mockito.plugins.MockMaker</code> containing the value <code>mock-maker-inline</code>.
*
* <p>
* As a convenience, the Mockito team provides an artifact where this mock maker is preconfigured. Instead of using the
Expand Down Expand Up @@ -1632,7 +1634,6 @@
* Specifying mock maker for individual mocks</a> (Since 4.8.0)</h3>
*
* You may encounter situations where you want to use a different mock maker for a specific test only.
* For example, you might want to migrate to the <a href="#0.2">inline mock maker</a>, but a few test do not work right away.
* In such case, you can (temporarily) use {@link MockSettings#mockMaker(String)} and {@link Mock#mockMaker()}
* to specify the mock maker for a specific mock which is causing the problem.
*
Expand All @@ -1647,7 +1648,7 @@
* <h3 id="54">54. <a class="meaningful_link" href="#mock_without_class" name="mock_without_class">
* Mocking/spying without specifying class</a> (Since 4.9.0)</h3>
*
* Instead of calling method {@link Mockito#mock(Class)} or {@link Mockito#spy(Class)} with Class parameter, you can now
* Instead of calling method {@link Mockito#mock(Class)} or {@link Mockito#spy(Class)} with Class parameter, you can
* now call method {@code mock()} or {@code spy()} <strong>without parameters</strong>:
*
* <pre class="code"><code class="java">
Expand All @@ -1661,6 +1662,19 @@
* With an implicit type, the Java compiler is unable to automatically determine the type of a mock and you need
* to pass in the {@code Class} explicitly.
* </p>
*
* <h3 id="55">55. <a class="meaningful_link" href="#verification_with_assertions" name="verification_with_assertions">
* Verification with assertions</a> (Since 5.3.0)</h3>
*
* To validate arguments during verification, instead of capturing them with {@link ArgumentCaptor}, you can now
* use {@link ArgumentMatchers#assertArg(Consumer)}}:
*
* <pre class="code"><code class="java">
* verify(serviceMock).doStuff(assertArg(param -&gt; {
* assertThat(param.getField1()).isEqualTo("foo");
* assertThat(param.getField2()).isEqualTo("bar");
* }));
* </code></pre>
*/
@CheckReturnValue
@SuppressWarnings("unchecked")
Expand Down Expand Up @@ -2167,6 +2181,10 @@ public static <T> T mock(Class<T> classToMock, MockSettings mockSettings) {
* @return a spy of the real object
*/
public static <T> T spy(T object) {
if (MockUtil.isMock(object)) {
throw new IllegalArgumentException(
"Please don't pass mock here. Spy is not allowed on mock.");
}
return MOCKITO_CORE.mock(
(Class<T>) object.getClass(),
withSettings().spiedInstance(object).defaultAnswer(CALLS_REAL_METHODS));
Expand Down
24 changes: 24 additions & 0 deletions src/main/java/org/mockito/ThrowingConsumer.java
@@ -0,0 +1,24 @@
/*
* Copyright (c) 2023 Mockito contributors
* This program is made available under the terms of the MIT License.
*/
package org.mockito;

import java.util.function.Consumer;

@SuppressWarnings("FunctionalInterfaceMethodChanged")
@FunctionalInterface
public interface ThrowingConsumer<T> extends Consumer<T> {
@Override
default void accept(final T input) {
try {
acceptThrows(input);
} catch (final RuntimeException | AssertionError e) {
throw e;
} catch (Throwable e) {
throw new RuntimeException(e);
}
}

void acceptThrows(T input) throws Throwable;
}
Expand Up @@ -56,6 +56,11 @@ public static Object processAnnotationForMock(
if (!annotation.mockMaker().isEmpty()) {
mockSettings.mockMaker(annotation.mockMaker());
}
if (annotation.withoutAnnotations()) {
mockSettings.withoutAnnotations();
}

mockSettings.genericTypeToMock(genericType.get());

// see @Mock answer default value
mockSettings.defaultAnswer(annotation.answer());
Expand Down
Expand Up @@ -87,6 +87,7 @@ private static Object spyInstance(Field field, Object instance) {
return Mockito.mock(
instance.getClass(),
withSettings()
.genericTypeToMock(field.getGenericType())
.spiedInstance(instance)
.defaultAnswer(CALLS_REAL_METHODS)
.name(field.getName()));
Expand All @@ -96,7 +97,10 @@ private static Object spyNewInstance(Object testInstance, Field field)
throws InstantiationException, IllegalAccessException, InvocationTargetException {
// TODO: Add mockMaker option for @Spy annotation (#2740)
MockSettings settings =
withSettings().defaultAnswer(CALLS_REAL_METHODS).name(field.getName());
withSettings()
.genericTypeToMock(field.getGenericType())
.defaultAnswer(CALLS_REAL_METHODS)
.name(field.getName());
Class<?> type = field.getType();
if (type.isInterface()) {
return Mockito.mock(type, settings.useConstructor());
Expand Down

0 comments on commit 1556f76

Please sign in to comment.