• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

hazendaz / jmockit1 / 496

15 Nov 2025 05:33PM UTC coverage: 72.192% (-0.008%) from 72.2%
496

push

github

web-flow
Merge pull request #412 from hazendaz/renovate/major-spring-core

Update spring core to v7 (major)

5677 of 8360 branches covered (67.91%)

Branch coverage included in aggregate %.

11922 of 16018 relevant lines covered (74.43%)

0.74 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.92
/main/src/main/java/mockit/internal/injection/constructor/ConstructorInjection.java
1
/*
2
 * MIT License
3
 * Copyright (c) 2006-2025 JMockit developers
4
 * See LICENSE file for full license text.
5
 */
6
package mockit.internal.injection.constructor;
7

8
import static mockit.internal.injection.InjectionPoint.getQualifiedName;
9
import static mockit.internal.injection.InjectionPoint.getTypeOfInjectionPointFromVarargsParameter;
10
import static mockit.internal.injection.InjectionPoint.kindOfInjectionPoint;
11
import static mockit.internal.injection.InjectionPoint.wrapInProviderIfNeeded;
12
import static mockit.internal.injection.InjectionProvider.NULL;
13
import static mockit.internal.reflection.ConstructorReflection.invokeAccessible;
14
import static mockit.internal.util.Utilities.NO_ARGS;
15
import static mockit.internal.util.Utilities.ensureThatMemberIsAccessible;
16
import static mockit.internal.util.Utilities.getClassType;
17

18
import edu.umd.cs.findbugs.annotations.NonNull;
19
import edu.umd.cs.findbugs.annotations.Nullable;
20

21
import java.lang.reflect.Array;
22
import java.lang.reflect.Constructor;
23
import java.lang.reflect.Type;
24
import java.util.ArrayList;
25
import java.util.List;
26

27
import mockit.asm.types.JavaType;
28
import mockit.internal.injection.InjectionPoint.KindOfInjectionPoint;
29
import mockit.internal.injection.InjectionProvider;
30
import mockit.internal.injection.InjectionProviders;
31
import mockit.internal.injection.InjectionState;
32
import mockit.internal.injection.Injector;
33
import mockit.internal.injection.TestedClass;
34
import mockit.internal.injection.full.FullInjection;
35
import mockit.internal.state.ParameterNames;
36
import mockit.internal.state.TestRun;
37
import mockit.internal.util.MethodFormatter;
38
import mockit.internal.util.StackTrace;
39

40
public final class ConstructorInjection extends Injector {
1✔
41
    @NonNull
42
    private final Constructor<?> constructor;
43

44
    public ConstructorInjection(@NonNull InjectionState injectionState, @Nullable FullInjection fullInjection,
45
            @NonNull Constructor<?> constructor) {
46
        super(injectionState, fullInjection);
1✔
47
        ensureThatMemberIsAccessible(constructor);
1✔
48
        this.constructor = constructor;
1✔
49
    }
1✔
50

51
    @Nullable
52
    public Object instantiate(@NonNull List<InjectionProvider> parameterProviders, @NonNull TestedClass testedClass,
53
            boolean required, boolean needToConstruct) {
54
        Type[] parameterTypes = constructor.getGenericParameterTypes();
1✔
55
        int n = parameterTypes.length;
1✔
56
        List<InjectionProvider> consumedInjectables = n == 0 ? null
1✔
57
                : injectionState.injectionProviders.saveConsumedInjectionProviders();
1✔
58
        Object[] arguments = n == 0 ? NO_ARGS : new Object[n];
1✔
59
        boolean varArgs = constructor.isVarArgs();
1✔
60

61
        if (varArgs) {
1✔
62
            n--;
1✔
63
        }
64

65
        for (int i = 0; i < n; i++) {
1✔
66
            @NonNull
67
            InjectionProvider parameterProvider = parameterProviders.get(i);
1✔
68
            Object value;
69

70
            if (parameterProvider instanceof ConstructorParameter) {
1✔
71
                value = createOrReuseArgumentValue((ConstructorParameter) parameterProvider, required);
1✔
72

73
                if (value == null && !needToConstruct) {
1✔
74
                    return null;
1✔
75
                }
76
            } else {
77
                value = getArgumentValueToInject(parameterProvider, i);
1✔
78
            }
79

80
            if (value != NULL) {
1✔
81
                Type parameterType = parameterTypes[i];
1✔
82
                arguments[i] = wrapInProviderIfNeeded(parameterType, value);
1✔
83
            }
84
        }
85

86
        if (varArgs) {
1✔
87
            Type parameterType = parameterTypes[n];
1✔
88
            arguments[n] = obtainInjectedVarargsArray(parameterType, testedClass);
1✔
89
        }
90

91
        if (consumedInjectables != null) {
1✔
92
            injectionState.injectionProviders.restoreConsumedInjectionProviders(consumedInjectables);
1✔
93
        }
94

95
        return invokeConstructor(arguments);
1✔
96
    }
97

98
    @Nullable
99
    private Object createOrReuseArgumentValue(@NonNull ConstructorParameter constructorParameter, boolean required) {
100
        Object givenValue = constructorParameter.getValue(null);
1✔
101

102
        if (givenValue != null) {
1✔
103
            return givenValue;
1✔
104
        }
105

106
        assert fullInjection != null;
1!
107

108
        Class<?> parameterClass = constructorParameter.getClassOfDeclaredType();
1✔
109
        Object newOrReusedValue = null;
1✔
110

111
        if (FullInjection.isInstantiableType(parameterClass)) {
1✔
112
            Type parameterType = constructorParameter.getDeclaredType();
1✔
113
            KindOfInjectionPoint kindOfInjectionPoint = kindOfInjectionPoint(constructor);
1✔
114
            injectionState.injectionProviders.setTypeOfInjectionPoint(parameterType, kindOfInjectionPoint);
1✔
115
            String qualifiedName = getQualifiedName(constructorParameter.getAnnotations());
1✔
116
            TestedClass nextTestedClass = new TestedClass(parameterType, parameterClass);
1✔
117

118
            newOrReusedValue = fullInjection.createOrReuseInstance(nextTestedClass, this, constructorParameter,
1✔
119
                    qualifiedName);
120
        } else {
1✔
121
            fullInjection.setInjectionProvider(constructorParameter);
1✔
122
        }
123

124
        if (newOrReusedValue == null && required) {
1✔
125
            String parameterName = constructorParameter.getName();
1✔
126
            String message = "Missing @Tested or @Injectable" + missingValueDescription(parameterName)
1✔
127
                    + "\r\n  when initializing " + fullInjection;
128
            IllegalStateException injectionFailure = new IllegalStateException(message);
1✔
129
            StackTrace.filterStackTrace(injectionFailure);
1✔
130
            throw injectionFailure;
1✔
131
        }
132

133
        return newOrReusedValue;
1✔
134
    }
135

136
    @NonNull
137
    private Object getArgumentValueToInject(@NonNull InjectionProvider injectable, int parameterIndex) {
138
        Object argument = injectionState.getValueToInject(injectable);
1✔
139

140
        if (argument == null) {
1✔
141
            String classDesc = getClassDesc();
1✔
142
            String constructorDesc = getConstructorDesc();
1✔
143
            String parameterName = ParameterNames.getName(classDesc, constructorDesc, parameterIndex);
1✔
144

145
            if (parameterName == null) {
1!
146
                parameterName = injectable.getName();
×
147
            }
148

149
            throw new IllegalArgumentException(
1✔
150
                    "No injectable value available" + missingValueDescription(parameterName));
1✔
151
        }
152

153
        return argument;
1✔
154
    }
155

156
    @NonNull
157
    private String getClassDesc() {
158
        return JavaType.getInternalName(constructor.getDeclaringClass());
1✔
159
    }
160

161
    @NonNull
162
    private String getConstructorDesc() {
163
        return "<init>" + JavaType.getConstructorDescriptor(constructor);
1✔
164
    }
165

166
    @NonNull
167
    private Object obtainInjectedVarargsArray(@NonNull Type parameterType, @NonNull TestedClass testedClass) {
168
        Type varargsElementType = getTypeOfInjectionPointFromVarargsParameter(parameterType);
1✔
169
        KindOfInjectionPoint kindOfInjectionPoint = kindOfInjectionPoint(constructor);
1✔
170
        InjectionProviders injectionProviders = injectionState.injectionProviders;
1✔
171
        injectionProviders.setTypeOfInjectionPoint(varargsElementType, kindOfInjectionPoint);
1✔
172

173
        List<Object> varargValues = new ArrayList<>();
1✔
174
        InjectionProvider injectable;
175

176
        while ((injectable = injectionProviders.findNextInjectableForInjectionPoint(testedClass)) != null) {
1✔
177
            Object value = injectionState.getValueToInject(injectable);
1✔
178

179
            if (value != null) {
1!
180
                value = wrapInProviderIfNeeded(varargsElementType, value);
1✔
181
                varargValues.add(value);
1✔
182
            }
183
        }
1✔
184

185
        return newArrayFromList(varargsElementType, varargValues);
1✔
186
    }
187

188
    @NonNull
189
    private static Object newArrayFromList(@NonNull Type elementType, @NonNull List<Object> values) {
190
        Class<?> componentType = getClassType(elementType);
1✔
191
        int elementCount = values.size();
1✔
192
        Object array = Array.newInstance(componentType, elementCount);
1✔
193

194
        for (int i = 0; i < elementCount; i++) {
1✔
195
            Array.set(array, i, values.get(i));
1✔
196
        }
197

198
        return array;
1✔
199
    }
200

201
    @NonNull
202
    private String missingValueDescription(@NonNull String name) {
203
        String classDesc = getClassDesc();
1✔
204
        String constructorDesc = getConstructorDesc();
1✔
205
        String constructorDescription = new MethodFormatter(classDesc, constructorDesc).toString();
1✔
206
        int p = constructorDescription.indexOf('#');
1✔
207
        // noinspection DynamicRegexReplaceableByCompiledPattern
208
        String friendlyConstructorDesc = constructorDescription.substring(p + 1).replace("java.lang.", "");
1✔
209

210
        return " for parameter \"" + name + "\" in constructor " + friendlyConstructorDesc;
1✔
211
    }
212

213
    @NonNull
214
    private Object invokeConstructor(@NonNull Object[] arguments) {
215
        TestRun.exitNoMockingZone();
1✔
216

217
        try {
218
            return invokeAccessible(constructor, arguments);
1✔
219
        } finally {
220
            TestRun.enterNoMockingZone();
1✔
221
        }
222
    }
223
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc