Repository: mockito/mockito
Issue: MockitoExtension cannot be registered as a global junit5 extension.
Labels: junit5

`MockitoExtension` doesn't expose its constructor so it can't be loaded by `ServiceLoader.`

When trying to register `MockitoExtension` for automatic use using a file named `META-INF\services\org.junit.jupiter.api.extension.Extension` and content `org.mockito.junit.jupiter.MockitoExtension`

the below error is thrown, using mockito-junit-jupiter 2.18.3

```
org.junit.jupiter.api.extension.Extension: org.mockito.junit.jupiter.MockitoExtension Unable to get public no-arg constructor
java.util.ServiceConfigurationError: org.junit.jupiter.api.extension.Extension: org.mockito.junit.jupiter.MockitoExtension Unable to get public no-arg constructor
	at java.base/java.util.ServiceLoader.fail(ServiceLoader.java:581)
	at java.base/java.util.ServiceLoader.getConstructor(ServiceLoader.java:672)
	at java.base/java.util.ServiceLoader.access$1000(ServiceLoader.java:390)
	at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNextService(ServiceLoader.java:1232)
	at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNext(ServiceLoader.java:1264)
	at java.base/java.util.ServiceLoader$2.hasNext(ServiceLoader.java:1299)
	at java.base/java.util.ServiceLoader$3.hasNext(ServiceLoader.java:1384)
	at java.base/java.lang.Iterable.forEach(Iterable.java:74)
	at org.junit.jupiter.engine.extension.ExtensionRegistry.registerAutoDetectedExtensions(ExtensionRegistry.java:102)
	at org.junit.jupiter.engine.extension.ExtensionRegistry.createRegistryWithDefaultExtensions(ExtensionRegistry.java:86)
	at org.junit.jupiter.engine.descriptor.JupiterEngineDescriptor.prepare(JupiterEngineDescriptor.java:37)
	at org.junit.jupiter.engine.descriptor.JupiterEngineDescriptor.prepare(JupiterEngineDescriptor.java:28)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.prepare(HierarchicalTestExecutor.java:89)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:74)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:55)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:43)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:170)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:154)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:90)
	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:92)
	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$100(JUnitPlatformTestClassProcessor.java:77)
	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:73)
	at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:564)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
	at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
	at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
	at com.sun.proxy.$Proxy1.stop(Unknown Source)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.stop(TestWorker.java:123)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:564)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
	at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:155)
	at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:137)
	at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404)
	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
	at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1135)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
	at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
	at java.base/java.lang.Thread.run(Thread.java:844)
Caused by: java.lang.NoSuchMethodException: org.mockito.junit.jupiter.MockitoExtension.<init>()
	at java.base/java.lang.Class.getConstructor0(Class.java:3302)
	at java.base/java.lang.Class.getConstructor(Class.java:2110)
	at java.base/java.util.ServiceLoader$1.run(ServiceLoader.java:659)
	at java.base/java.util.ServiceLoader$1.run(ServiceLoader.java:656)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at java.base/java.util.ServiceLoader.getConstructor(ServiceLoader.java:667)
	... 46 more
```

 - [X] The mockito message in the stacktrace have useful information, but it didn't help
 - [X] The problematic code (if that's possible) is copied here;
       Note that some configuration are impossible to mock via Mockito
 - [X] Provide versions (mockito / jdk / os / any other relevant information)
 - [X] Provide a [Short, Self Contained, Correct (Compilable), Example](http://sscce.org) of the issue
       (same as any question on stackoverflow.com)
 - [X] Read the [contributing guide](https://github.com/mockito/mockito/blob/master/.github/CONTRIBUTING.md)

Issue comments:

Pull request review comments:

Patch that resolved the issue:
diff --git a/settings.gradle b/settings.gradle
index 67fdf19066..74b7a84452 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -5,6 +5,7 @@ include 'extTest'
 include 'kotlinTest'
 include 'android'
 include 'junit-jupiter'
+include 'junitJupiterExtensionTest'
 
 rootProject.name = 'mockito'
 
diff --git a/subprojects/junit-jupiter/src/main/java/org/mockito/junit/jupiter/MockitoExtension.java b/subprojects/junit-jupiter/src/main/java/org/mockito/junit/jupiter/MockitoExtension.java
index 1ee5a3e02c..ad1d434d3d 100644
--- a/subprojects/junit-jupiter/src/main/java/org/mockito/junit/jupiter/MockitoExtension.java
+++ b/subprojects/junit-jupiter/src/main/java/org/mockito/junit/jupiter/MockitoExtension.java
@@ -66,9 +66,9 @@ public class MockitoExtension implements TestInstancePostProcessor,BeforeEachCal
 
     private final Strictness strictness;
 
-    // This constructor is invoked by JUnit Jupiter via reflection
+    // This constructor is invoked by JUnit Jupiter via reflection or ServiceLoader
     @SuppressWarnings("unused")
-    private MockitoExtension() {
+    public MockitoExtension() {
         this(Strictness.STRICT_STUBS);
     }
 
diff --git a/subprojects/junitJupiterExtensionTest/junitJupiterExtensionTest.gradle b/subprojects/junitJupiterExtensionTest/junitJupiterExtensionTest.gradle
new file mode 100644
index 0000000000..1761dcd46d
--- /dev/null
+++ b/subprojects/junitJupiterExtensionTest/junitJupiterExtensionTest.gradle
@@ -0,0 +1,18 @@
+apply from: "$rootDir/gradle/dependencies.gradle"
+
+apply plugin: 'java'
+description = "End-to-end tests for automatic registration of MockitoExtension."
+
+sourceCompatibility = 1.8
+
+dependencies {
+    testCompile project(":junit-jupiter")
+    testCompile libraries.assertj
+    testCompile libraries.junitPlatformLauncher
+    testCompile libraries.junitJupiterApi
+    testRuntime libraries.junitJupiterEngine
+}
+
+test {
+    useJUnitPlatform()
+}


Test patch:
diff --git a/subprojects/junitJupiterExtensionTest/src/test/java/org/mockitousage/NoExtendsTest.java b/subprojects/junitJupiterExtensionTest/src/test/java/org/mockitousage/NoExtendsTest.java
new file mode 100644
index 0000000000..a0d545c6b1
--- /dev/null
+++ b/subprojects/junitJupiterExtensionTest/src/test/java/org/mockitousage/NoExtendsTest.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2018 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage;
+
+
+import java.util.List;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mock;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.when;
+
+class NoExtendsTest {
+
+    @Mock
+    private List<String> mock;
+
+    @Test
+    void runs() {
+        when(mock.get(0)).thenReturn("foo");
+        assertThat(mock.get(0)).isEqualTo("foo");
+    }
+}
diff --git a/subprojects/junitJupiterExtensionTest/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension b/subprojects/junitJupiterExtensionTest/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension
new file mode 100644
index 0000000000..02593efe36
--- /dev/null
+++ b/subprojects/junitJupiterExtensionTest/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension
@@ -0,0 +1,1 @@
+org.mockito.junit.jupiter.MockitoExtension
diff --git a/subprojects/junitJupiterExtensionTest/src/test/resources/junit-platform.properties b/subprojects/junitJupiterExtensionTest/src/test/resources/junit-platform.properties
new file mode 100644
index 0000000000..25ce5c9844
--- /dev/null
+++ b/subprojects/junitJupiterExtensionTest/src/test/resources/junit-platform.properties
@@ -0,0 +1,1 @@
+junit.jupiter.extensions.autodetection.enabled = true