Skip to content

Commit b6554b2

Browse files
authored
Fix interference between spies when spying on records (#3173)
Fixes #3160 Co-authored-by: Mikaël Francoeur <[email protected]>
1 parent bfee15d commit b6554b2

File tree

3 files changed

+33
-5
lines changed

3 files changed

+33
-5
lines changed

src/main/java/org/mockito/internal/creation/bytebuddy/InlineDelegateByteBuddyMockMaker.java

+7-5
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ class InlineDelegateByteBuddyMockMaker
218218
private final DetachedThreadLocal<Map<Class<?>, BiConsumer<Object, MockedConstruction.Context>>>
219219
mockedConstruction = new DetachedThreadLocal<>(DetachedThreadLocal.Cleaner.MANUAL);
220220

221-
private final ThreadLocal<Boolean> mockitoConstruction = ThreadLocal.withInitial(() -> false);
221+
private final ThreadLocal<Class<?>> currentMocking = ThreadLocal.withInitial(() -> null);
222222

223223
private final ThreadLocal<Object> currentSpied = new ThreadLocal<>();
224224

@@ -272,7 +272,9 @@ class InlineDelegateByteBuddyMockMaker
272272
type -> {
273273
if (isSuspended.get()) {
274274
return false;
275-
} else if (mockitoConstruction.get() || currentConstruction.get() != null) {
275+
} else if ((currentMocking.get() != null
276+
&& type.isAssignableFrom(currentMocking.get()))
277+
|| currentConstruction.get() != null) {
276278
return true;
277279
}
278280
Map<Class<?>, ?> interceptors = mockedConstruction.get();
@@ -290,7 +292,7 @@ class InlineDelegateByteBuddyMockMaker
290292
};
291293
ConstructionCallback onConstruction =
292294
(type, object, arguments, parameterTypeNames) -> {
293-
if (mockitoConstruction.get()) {
295+
if (currentMocking.get() != null) {
294296
Object spy = currentSpied.get();
295297
if (spy == null) {
296298
return null;
@@ -647,11 +649,11 @@ public <T> T newInstance(Class<T> cls) throws InstantiationException {
647649
accessor.newInstance(
648650
selected,
649651
callback -> {
650-
mockitoConstruction.set(true);
652+
currentMocking.set(cls);
651653
try {
652654
return callback.newInstance();
653655
} finally {
654-
mockitoConstruction.set(false);
656+
currentMocking.remove();
655657
}
656658
},
657659
arguments);

subprojects/java21/src/test/java/org/mockito/java21/.gitkeep

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright (c) 2023 Mockito contributors
3+
* This program is made available under the terms of the MIT License.
4+
*/
5+
package org.mockito.java21;
6+
7+
import static org.assertj.core.api.Assertions.assertThat;
8+
import static org.mockito.Mockito.spy;
9+
10+
import java.util.List;
11+
12+
import org.junit.Test;
13+
14+
public class RecordTest {
15+
16+
@Test
17+
public void given_list_is_already_spied__when_spying_record__then_record_fields_are_correctly_populated() {
18+
var ignored = spy(List.of());
19+
20+
record MyRecord(String name) {
21+
}
22+
MyRecord spiedRecord = spy(new MyRecord("something"));
23+
24+
assertThat(spiedRecord.name()).isEqualTo("something");
25+
}
26+
}

0 commit comments

Comments
 (0)