From 93aa0b94a4793376c9880f5f9904dacd93e013a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Pfr=C3=BCnder?= Date: Wed, 29 Dec 2021 10:45:58 +0100 Subject: [PATCH] add support for classes with one constructor but without annotation --- .../org/hypoport/mockito/MockInjector.java | 27 ++++++++++++----- ...ructorInjectionClassWithoutAnnotation.java | 29 +++++++++++++++++++ .../mockito/injection/MockInjectorTest.java | 8 +++++ 3 files changed, 57 insertions(+), 7 deletions(-) create mode 100644 src/test/java/org/hypoport/mockito/injection/ConstructorInjectionClassWithoutAnnotation.java diff --git a/src/main/java/org/hypoport/mockito/MockInjector.java b/src/main/java/org/hypoport/mockito/MockInjector.java index 5246ee9..5147864 100644 --- a/src/main/java/org/hypoport/mockito/MockInjector.java +++ b/src/main/java/org/hypoport/mockito/MockInjector.java @@ -65,16 +65,15 @@ public static T injectMocks(Class clazz) { Constructor[] constructors = clazz.getDeclaredConstructors(); for (Constructor constructor : constructors) { if (shouldBeInjected(constructor.getDeclaredAnnotations()) || constructor.getParameterTypes().length == 0) { - constructor.setAccessible(true); - Class[] parameterTypes = constructor.getParameterTypes(); - Object[] mocks = createMocksForParameterTypes(parameterTypes); - T instantiated = (T) constructor.newInstance(mocks); - injectFieldsAndSetters(instantiated, clazz); - return instantiated; + return createObjectAndInjectMocks(clazz, constructor); } } + // no annotated constructor found: + if (constructors.length == 1) { + return createObjectAndInjectMocks(clazz, constructors[0]); + } // we hopefully never get here: - throw new RuntimeException("no constructor found for class " + clazz); + throw new RuntimeException("no usable constructor found for class " + clazz); } catch (RuntimeException e) { throw e; } catch (Exception e) { @@ -82,6 +81,20 @@ public static T injectMocks(Class clazz) { } } + private static T createObjectAndInjectMocks(Class clazz, Constructor constructor) throws InstantiationException, IllegalAccessException, InvocationTargetException { + T instantiated = createObjectUsingConstructor(constructor); + injectFieldsAndSetters(instantiated, clazz); + return instantiated; + } + + private static T createObjectUsingConstructor(Constructor constructor) throws InstantiationException, IllegalAccessException, InvocationTargetException { + constructor.setAccessible(true); + Class[] parameterTypes = constructor.getParameterTypes(); + Object[] mocks = createMocksForParameterTypes(parameterTypes); + T instantiated = (T) constructor.newInstance(mocks); + return instantiated; + } + public static void injectFieldsAndSetters(Object object, Class objectClass) throws IllegalAccessException, InvocationTargetException { injectFields(object, objectClass); injectSetter(object, objectClass); diff --git a/src/test/java/org/hypoport/mockito/injection/ConstructorInjectionClassWithoutAnnotation.java b/src/test/java/org/hypoport/mockito/injection/ConstructorInjectionClassWithoutAnnotation.java new file mode 100644 index 0000000..7a27b43 --- /dev/null +++ b/src/test/java/org/hypoport/mockito/injection/ConstructorInjectionClassWithoutAnnotation.java @@ -0,0 +1,29 @@ +/** + * Copyright 2022 HYPOPORT AG + * + * 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.hypoport.mockito.injection; + +import javax.inject.Inject; + +public class ConstructorInjectionClassWithoutAnnotation { + + MyClass toBeInjected1; + Object toBeInjected2; + + private ConstructorInjectionClassWithoutAnnotation(MyClass toBeInjected1, Object toBeInjected2) { + this.toBeInjected1 = toBeInjected1; + this.toBeInjected2 = toBeInjected2; + } +} diff --git a/src/test/java/org/hypoport/mockito/injection/MockInjectorTest.java b/src/test/java/org/hypoport/mockito/injection/MockInjectorTest.java index 52ca784..0d1e88d 100644 --- a/src/test/java/org/hypoport/mockito/injection/MockInjectorTest.java +++ b/src/test/java/org/hypoport/mockito/injection/MockInjectorTest.java @@ -91,4 +91,12 @@ public void injectMocks_with_Class_can_handle_Constructor_Injection() { Assertions.assertThat(MockUtil.isMock(object.toBeInjected2)).isTrue(); } + @Test + public void injectMocks_with_Class_can_handle_Constructor_Injection_without_annotation() { + ConstructorInjectionClassWithoutAnnotation object = MockInjector.injectMocks(ConstructorInjectionClassWithoutAnnotation.class); + + Assertions.assertThat(MockUtil.isMock(object.toBeInjected1)).isTrue(); + Assertions.assertThat(MockUtil.isMock(object.toBeInjected2)).isTrue(); + } + }