/* * Copyright (c) 2007 Mockito contributors * This program is made available under the terms of the MIT License. */ package org.mockitousage.basicapi; import org.assertj.core.api.Assertions; import org.junit.Test; import org.mockito.InOrder; import org.mockito.Mockito; import org.mockito.internal.matchers.Any; import org.mockito.internal.stubbing.answers.ThrowsException; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.mockitousage.IMethods; import org.mockitoutil.SimpleSerializationUtil; import org.mockitoutil.TestBase; import java.io.ByteArrayOutputStream; import java.io.ObjectStreamException; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Observable; import static junit.framework.TestCase.*; import static org.junit.Assume.assumeFalse; import static org.mockito.Mockito.*; import static org.mockitoutil.SimpleSerializationUtil.*; @SuppressWarnings({"unchecked", "serial"}) public class MocksSerializationTest extends TestBase implements Serializable { private static final long serialVersionUID = 6160482220413048624L; @Test public void should_allow_throws_exception_to_be_serializable() throws Exception { // given Bar mock = mock(Bar.class, new ThrowsException(new RuntimeException())); // when-serialize then-deserialize serializeAndBack(mock); } @Test public void should_allow_method_delegation() throws Exception { // given Bar barMock = mock(Bar.class, withSettings().serializable()); Foo fooMock = mock(Foo.class); when(barMock.doSomething()).thenAnswer(new ThrowsException(new RuntimeException())); //when-serialize then-deserialize serializeAndBack(barMock); } @Test public void should_allow_mock_to_be_serializable() throws Exception { // given IMethods mock = mock(IMethods.class, withSettings().serializable()); // when-serialize then-deserialize serializeAndBack(mock); } @Test public void should_allow_mock_and_boolean_value_to_serializable() throws Exception { // given IMethods mock = mock(IMethods.class, withSettings().serializable()); when(mock.booleanReturningMethod()).thenReturn(true); // when ByteArrayOutputStream serialized = serializeMock(mock); // then IMethods readObject = deserializeMock(serialized, IMethods.class); assertTrue(readObject.booleanReturningMethod()); } @Test public void should_allow_mock_and_string_value_to_be_serializable() throws Exception { // given IMethods mock = mock(IMethods.class, withSettings().serializable()); String value = "value"; when(mock.stringReturningMethod()).thenReturn(value); // when ByteArrayOutputStream serialized = serializeMock(mock); // then IMethods readObject = deserializeMock(serialized, IMethods.class); assertEquals(value, readObject.stringReturningMethod()); } @Test public void should_all_mock_and_serializable_value_to_be_serialized() throws Exception { // given IMethods mock = mock(IMethods.class, withSettings().serializable()); List<?> value = Collections.emptyList(); when(mock.objectReturningMethodNoArgs()).thenReturn(value); // when ByteArrayOutputStream serialized = serializeMock(mock); // then IMethods readObject = deserializeMock(serialized, IMethods.class); assertEquals(value, readObject.objectReturningMethodNoArgs()); } @Test public void should_serialize_method_call_with_parameters_that_are_serializable() throws Exception { IMethods mock = mock(IMethods.class, withSettings().serializable()); List<?> value = Collections.emptyList(); when(mock.objectArgMethod(value)).thenReturn(value); // when ByteArrayOutputStream serialized = serializeMock(mock); // then IMethods readObject = deserializeMock(serialized, IMethods.class); assertEquals(value, readObject.objectArgMethod(value)); } @Test public void should_serialize_method_calls_using_any_string_matcher() throws Exception { IMethods mock = mock(IMethods.class, withSettings().serializable()); List<?> value = Collections.emptyList(); when(mock.objectArgMethod(anyString())).thenReturn(value); // when ByteArrayOutputStream serialized = serializeMock(mock); // then IMethods readObject = deserializeMock(serialized, IMethods.class); assertEquals(value, readObject.objectArgMethod("")); } @Test public void should_verify_called_n_times_for_serialized_mock() throws Exception { IMethods mock = mock(IMethods.class, withSettings().serializable()); List<?> value = Collections.emptyList(); when(mock.objectArgMethod(anyString())).thenReturn(value); mock.objectArgMethod(""); // when ByteArrayOutputStream serialized = serializeMock(mock); // then IMethods readObject = deserializeMock(serialized, IMethods.class); verify(readObject, times(1)).objectArgMethod(""); } @Test public void should_verify_even_if_some_methods_called_after_serialization() throws Exception { //given IMethods mock = mock(IMethods.class, withSettings().serializable()); // when mock.simpleMethod(1); ByteArrayOutputStream serialized = serializeMock(mock); IMethods readObject = deserializeMock(serialized, IMethods.class); readObject.simpleMethod(1); // then verify(readObject, times(2)).simpleMethod(1); //this test is working because it seems that java serialization mechanism replaces all instances //of serialized object in the object graph (if there are any) } class Bar implements Serializable { Foo foo; public Foo doSomething() { return foo; } } class Foo implements Serializable { Bar bar; Foo() { bar = new Bar(); bar.foo = this; } } @Test public void should_serialization_work() throws Exception { //given Foo foo = new Foo(); //when foo = serializeAndBack(foo); //then assertSame(foo, foo.bar.foo); } @Test public void should_stub_even_if_some_methods_called_after_serialization() throws Exception { //given IMethods mock = mock(IMethods.class, withSettings().serializable()); // when when(mock.simpleMethod(1)).thenReturn("foo"); ByteArrayOutputStream serialized = serializeMock(mock); IMethods readObject = deserializeMock(serialized, IMethods.class); when(readObject.simpleMethod(2)).thenReturn("bar"); // then assertEquals("foo", readObject.simpleMethod(1)); assertEquals("bar", readObject.simpleMethod(2)); } @Test public void should_verify_call_order_for_serialized_mock() throws Exception { IMethods mock = mock(IMethods.class, withSettings().serializable()); IMethods mock2 = mock(IMethods.class, withSettings().serializable()); mock.arrayReturningMethod(); mock2.arrayReturningMethod(); // when ByteArrayOutputStream serialized = serializeMock(mock); ByteArrayOutputStream serialized2 = serializeMock(mock2); // then IMethods readObject = deserializeMock(serialized, IMethods.class); IMethods readObject2 = deserializeMock(serialized2, IMethods.class); InOrder inOrder = inOrder(readObject, readObject2); inOrder.verify(readObject).arrayReturningMethod(); inOrder.verify(readObject2).arrayReturningMethod(); } @Test public void should_remember_interactions_for_serialized_mock() throws Exception { IMethods mock = mock(IMethods.class, withSettings().serializable()); List<?> value = Collections.emptyList(); when(mock.objectArgMethod(anyString())).thenReturn(value); mock.objectArgMethod("happened"); // when ByteArrayOutputStream serialized = serializeMock(mock); // then IMethods readObject = deserializeMock(serialized, IMethods.class); verify(readObject, never()).objectArgMethod("never happened"); } @Test public void should_serialize_with_stubbing_callback() throws Exception { // given IMethods mock = mock(IMethods.class, withSettings().serializable()); CustomAnswersMustImplementSerializableForSerializationToWork answer = new CustomAnswersMustImplementSerializableForSerializationToWork(); answer.string = "return value"; when(mock.objectArgMethod(anyString())).thenAnswer(answer); // when ByteArrayOutputStream serialized = serializeMock(mock); // then IMethods readObject = deserializeMock(serialized, IMethods.class); assertEquals(answer.string, readObject.objectArgMethod("")); } class CustomAnswersMustImplementSerializableForSerializationToWork implements Answer<Object>, Serializable { private String string; public Object answer(InvocationOnMock invocation) throws Throwable { invocation.getArguments(); invocation.getMock(); return string; } } @Test public void should_serialize_with_real_object_spy() throws Exception { // given List<Object> list = new ArrayList<Object>(); List<Object> spy = mock(ArrayList.class, withSettings() .spiedInstance(list) .defaultAnswer(CALLS_REAL_METHODS) .serializable()); when(spy.size()).thenReturn(100); // when ByteArrayOutputStream serialized = serializeMock(spy); // then List<?> readObject = deserializeMock(serialized, List.class); assertEquals(100, readObject.size()); } @Test public void should_serialize_object_mock() throws Exception { // given Any mock = mock(Any.class); // when ByteArrayOutputStream serialized = serializeMock(mock); // then deserializeMock(serialized, Any.class); } @Test public void should_serialize_real_partial_mock() throws Exception { // given Any mock = mock(Any.class, withSettings().serializable()); when(mock.matches(anyObject())).thenCallRealMethod(); // when ByteArrayOutputStream serialized = serializeMock(mock); // then Any readObject = deserializeMock(serialized, Any.class); readObject.matches(""); } class AlreadySerializable implements Serializable {} @Test public void should_serialize_already_serializable_class() throws Exception { // given AlreadySerializable mock = mock(AlreadySerializable.class, withSettings().serializable()); when(mock.toString()).thenReturn("foo"); // when mock = serializeAndBack(mock); // then assertEquals("foo", mock.toString()); } @Test public void should_be_serialize_and_have_extra_interfaces() throws Exception { //when IMethods mock = mock(IMethods.class, withSettings().serializable().extraInterfaces(List.class)); IMethods mockTwo = mock(IMethods.class, withSettings().extraInterfaces(List.class).serializable()); //then Assertions.assertThat((Object) serializeAndBack((List) mock)) .isInstanceOf(List.class) .isInstanceOf(IMethods.class); Assertions.assertThat((Object) serializeAndBack((List) mockTwo)) .isInstanceOf(List.class) .isInstanceOf(IMethods.class); } static class SerializableAndNoDefaultConstructor implements Serializable { SerializableAndNoDefaultConstructor(Observable o) { super(); } } @Test public void should_be_able_to_serialize_type_that_implements_Serializable_but_but_dont_declare_a_no_arg_constructor() throws Exception { serializeAndBack(mock(SerializableAndNoDefaultConstructor.class)); } public static class AClassWithPrivateNoArgConstructor { private AClassWithPrivateNoArgConstructor() {} List returningSomething() { return Collections.emptyList(); } } @Test public void private_constructor_currently_not_supported_at_the_moment_at_deserialization_time() throws Exception { // given AClassWithPrivateNoArgConstructor mockWithPrivateConstructor = Mockito.mock( AClassWithPrivateNoArgConstructor.class, Mockito.withSettings().serializable() ); try { // when SimpleSerializationUtil.serializeAndBack(mockWithPrivateConstructor); fail("should have thrown an ObjectStreamException or a subclass of it"); } catch (ObjectStreamException e) { // then Assertions.assertThat(e.toString()).contains("no valid constructor"); } } @Test public void BUG_ISSUE_399_try_some_mocks_with_current_answers() throws Exception { assumeFalse(System.getProperty("java.version").startsWith("1.6")); // Bug in last public HotSpot 1.6 IMethods iMethods = mock(IMethods.class, withSettings().serializable().defaultAnswer(RETURNS_DEEP_STUBS)); when(iMethods.iMethodsReturningMethod().linkedListReturningMethod().contains(anyString())).thenReturn(false); serializeAndBack(iMethods); } }