1/*
2 * Copyright (c) 2007 Mockito contributors
3 * This program is made available under the terms of the MIT License.
4 */
5package org.mockitousage.stubbing;
6
7import org.junit.Test;
8import org.mockito.Mockito;
9import org.mockito.exceptions.base.MockitoException;
10import org.mockitousage.IMethods;
11import org.mockitousage.MethodsImpl;
12
13import java.util.ArrayList;
14import java.util.Collection;
15import java.util.List;
16
17import static junit.framework.TestCase.assertEquals;
18import static org.assertj.core.api.Assertions.assertThat;
19import static org.junit.Assert.fail;
20import static org.mockito.AdditionalAnswers.delegatesTo;
21import static org.mockito.Mockito.doReturn;
22import static org.mockito.Mockito.mock;
23
24@SuppressWarnings("unchecked")
25public class StubbingWithDelegateTest {
26    public class FakeList<T> {
27        private T value;
28
29        public T get(int i) {
30            return value;
31        }
32
33        public T set(int i, T value) {
34            this.value = value;
35            return value;
36        }
37
38        public int size() {
39            return 10;
40        }
41
42        public ArrayList<T> subList(int fromIndex, int toIndex) {
43            return new ArrayList<T>();
44        }
45    }
46
47    public class FakeListWithWrongMethods<T> {
48        public double size() {
49            return 10;
50        }
51
52        public Collection<T> subList(int fromIndex, int toIndex) {
53            return new ArrayList<T>();
54        }
55    }
56
57    @Test
58    public void when_not_stubbed_delegate_should_be_called() {
59        List<String> delegatedList = new ArrayList<String>();
60        delegatedList.add("un");
61
62        List<String> mock = mock(List.class, delegatesTo(delegatedList));
63
64        mock.add("two");
65
66        assertEquals(2, mock.size());
67    }
68
69    @Test
70    public void when_stubbed_the_delegate_should_not_be_called() {
71        List<String> delegatedList = new ArrayList<String>();
72        delegatedList.add("un");
73        List<String> mock = mock(List.class, delegatesTo(delegatedList));
74
75        doReturn(10).when(mock).size();
76
77        mock.add("two");
78
79        assertEquals(10, mock.size());
80        assertEquals(2, delegatedList.size());
81    }
82
83    @Test
84    public void delegate_should_not_be_called_when_stubbed2() {
85        List<String> delegatedList = new ArrayList<String>();
86        delegatedList.add("un");
87        List<String> mockedList = mock(List.class, delegatesTo(delegatedList));
88
89        doReturn(false).when(mockedList).add(Mockito.anyString());
90
91        mockedList.add("two");
92
93        assertEquals(1, mockedList.size());
94        assertEquals(1, delegatedList.size());
95    }
96
97    @Test
98    public void null_wrapper_dont_throw_exception_from_org_mockito_package() throws Exception {
99        IMethods methods = mock(IMethods.class, delegatesTo(new MethodsImpl()));
100
101        try {
102            byte b = methods.byteObjectReturningMethod(); // real method returns null
103            fail();
104        } catch (Exception e) {
105            assertThat(e.toString()).doesNotContain("org.mockito");
106        }
107    }
108
109    @Test
110    public void instance_of_different_class_can_be_called() {
111        List<String> mock = mock(List.class, delegatesTo(new FakeList<String>()));
112
113        mock.set(1, "1");
114        assertThat(mock.get(1).equals("1"));
115    }
116
117    @Test
118    public void method_with_subtype_return_can_be_called() {
119        List<String> mock = mock(List.class, delegatesTo(new FakeList<String>()));
120
121        List<String> subList = mock.subList(0, 0);
122        assertThat(subList.isEmpty());
123    }
124
125    @Test
126    public void calling_missing_method_should_throw_exception() {
127        List<String> mock = mock(List.class, delegatesTo(new FakeList<String>()));
128
129        try {
130            mock.isEmpty();
131            fail();
132        } catch (MockitoException e) {
133            assertThat(e.toString()).contains("Methods called on mock must exist");
134        }
135    }
136
137    @Test
138    public void calling_method_with_wrong_primitive_return_should_throw_exception() {
139        List<String> mock = mock(List.class, delegatesTo(new FakeListWithWrongMethods<String>()));
140
141        try {
142            mock.size();
143            fail();
144        } catch (MockitoException e) {
145            assertThat(e.toString()).contains("Methods called on delegated instance must have compatible return type");
146        }
147    }
148
149    @Test
150    public void calling_method_with_wrong_reference_return_should_throw_exception() {
151        List<String> mock = mock(List.class, delegatesTo(new FakeListWithWrongMethods<String>()));
152
153        try {
154            mock.subList(0, 0);
155            fail();
156        } catch (MockitoException e) {
157            assertThat(e.toString()).contains("Methods called on delegated instance must have compatible return type");
158        }
159    }
160
161    @Test
162    public void exception_should_be_propagated_from_delegate() throws Exception {
163        final RuntimeException failure = new RuntimeException("angry-method");
164        IMethods methods = mock(IMethods.class, delegatesTo(new MethodsImpl() {
165            @Override
166            public String simpleMethod() {
167                throw failure;
168            }
169        }));
170
171        try {
172            methods.simpleMethod(); // delegate throws an exception
173            fail();
174        } catch (RuntimeException e) {
175            assertThat(e).isEqualTo(failure);
176        }
177    }
178}
179