1 /* 2 * Copyright (c) 2007 Mockito contributors 3 * This program is made available under the terms of the MIT License. 4 */ 5 package org.mockitousage.serialization; 6 7 import static org.assertj.core.api.Assertions.assertThat; 8 9 import java.io.ByteArrayInputStream; 10 import java.util.Collections; 11 import java.util.List; 12 import java.util.concurrent.Callable; 13 14 import net.bytebuddy.ClassFileVersion; 15 import org.junit.Before; 16 import org.junit.Test; 17 import org.mockito.Mockito; 18 import org.mockito.mock.SerializableMode; 19 import org.mockitousage.IMethods; 20 import org.mockitoutil.SimplePerRealmReloadingClassLoader; 21 import org.mockitoutil.SimpleSerializationUtil; 22 23 public class AcrossClassLoaderSerializationTest { 24 25 public IMethods mock; 26 27 @Before reproduce_CCE_by_creating_a_mock_with_IMethods_before()28 public void reproduce_CCE_by_creating_a_mock_with_IMethods_before() throws Exception { 29 mock = Mockito.mock(IMethods.class); 30 } 31 32 @Test check_that_mock_can_be_serialized_in_a_classloader_and_deserialized_in_another()33 public void check_that_mock_can_be_serialized_in_a_classloader_and_deserialized_in_another() 34 throws Exception { 35 // No longer supported starting with JDK 16+ 36 if (!ClassFileVersion.ofThisVm().isAtMost(ClassFileVersion.JAVA_V16)) { 37 return; 38 } 39 byte[] bytes = create_mock_and_serialize_it_in_class_loader_A(); 40 41 Object the_deserialized_mock = read_stream_and_deserialize_it_in_class_loader_B(bytes); 42 assertThat(the_deserialized_mock.getClass().getName()) 43 .startsWith("org.mockito.codegen.AClassToBeMockedInThisTestOnlyAndInCallablesOnly"); 44 } 45 read_stream_and_deserialize_it_in_class_loader_B(byte[] bytes)46 private Object read_stream_and_deserialize_it_in_class_loader_B(byte[] bytes) throws Exception { 47 return new SimplePerRealmReloadingClassLoader( 48 this.getClass().getClassLoader(), isolating_test_classes()) 49 .doInRealm( 50 "org.mockitousage.serialization.AcrossClassLoaderSerializationTest$ReadStreamAndDeserializeIt", 51 new Class<?>[] {byte[].class}, 52 new Object[] {bytes}); 53 } 54 create_mock_and_serialize_it_in_class_loader_A()55 private byte[] create_mock_and_serialize_it_in_class_loader_A() throws Exception { 56 return (byte[]) 57 new SimplePerRealmReloadingClassLoader( 58 this.getClass().getClassLoader(), isolating_test_classes()) 59 .doInRealm( 60 "org.mockitousage.serialization.AcrossClassLoaderSerializationTest$CreateMockAndSerializeIt"); 61 } 62 isolating_test_classes()63 private SimplePerRealmReloadingClassLoader.ReloadClassPredicate isolating_test_classes() { 64 return new SimplePerRealmReloadingClassLoader.ReloadClassPredicate() { 65 public boolean acceptReloadOf(String qualifiedName) { 66 return qualifiedName.contains("org.mockitousage") 67 || qualifiedName.contains("org.mockitoutil"); 68 } 69 }; 70 } 71 72 // see create_mock_and_serialize_it_in_class_loader_A 73 public static class CreateMockAndSerializeIt implements Callable<byte[]> { 74 public byte[] call() throws Exception { 75 AClassToBeMockedInThisTestOnlyAndInCallablesOnly mock = 76 Mockito.mock( 77 AClassToBeMockedInThisTestOnlyAndInCallablesOnly.class, 78 Mockito.withSettings() 79 .serializable(SerializableMode.ACROSS_CLASSLOADERS)); 80 // use MethodProxy before 81 mock.returningSomething(); 82 83 return SimpleSerializationUtil.serializeMock(mock).toByteArray(); 84 } 85 } 86 87 // see read_stream_and_deserialize_it_in_class_loader_B 88 public static class ReadStreamAndDeserializeIt implements Callable<Object> { 89 private byte[] bytes; 90 91 public ReadStreamAndDeserializeIt(byte[] bytes) { 92 this.bytes = bytes; 93 } 94 95 public Object call() throws Exception { 96 ByteArrayInputStream to_unserialize = new ByteArrayInputStream(bytes); 97 return SimpleSerializationUtil.deserializeMock( 98 to_unserialize, AClassToBeMockedInThisTestOnlyAndInCallablesOnly.class); 99 } 100 } 101 102 public static class AClassToBeMockedInThisTestOnlyAndInCallablesOnly { 103 List returningSomething() { 104 return Collections.emptyList(); 105 } 106 } 107 } 108