1/*
2 * Copyright (c) 2007 Mockito contributors
3 * This program is made available under the terms of the MIT License.
4 */
5package org.mockito;
6
7import org.mockito.stubbing.Answer;
8import org.mockito.stubbing.OngoingStubbing;
9import org.mockito.stubbing.Stubber;
10
11/**
12 * Behavior Driven Development style of writing tests uses <b>//given //when //then</b> comments as fundamental parts of your test methods.
13 * This is exactly how we write our tests and we warmly encourage you to do so!
14 * <p>
15 * Start learning about BDD here: <a href="http://en.wikipedia.org/wiki/Behavior_Driven_Development">http://en.wikipedia.org/wiki/Behavior_Driven_Development</a>
16 * <p>
17 * The problem is that current stubbing api with canonical role of <b>when</b> word does not integrate nicely with <b>//given //when //then</b> comments.
18 * It's because stubbing belongs to <b>given</b> component of the test and not to the <b>when</b> component of the test.
19 * Hence {@link BDDMockito} class introduces an alias so that you stub method calls with {@link BDDMockito#given(Object)} method.
20 * Now it really nicely integrates with the <b>given</b> component of a BDD style test!
21 * <p>
22 * Here is how the test might look like:
23 * <pre class="code"><code class="java">
24 * import static org.mockito.BDDMockito.*;
25 *
26 * Seller seller = mock(Seller.class);
27 * Shop shop = new Shop(seller);
28 *
29 * public void shouldBuyBread() throws Exception {
30 *   //given
31 *   given(seller.askForBread()).willReturn(new Bread());
32 *
33 *   //when
34 *   Goods goods = shop.buyBread();
35 *
36 *   //then
37 *   assertThat(goods, containBread());
38 * }
39 * </code></pre>
40 *
41 * Stubbing voids with throwables:
42 * <pre class="code"><code class="java">
43 *   //given
44 *   willThrow(new RuntimeException("boo")).given(mock).foo();
45 *
46 *   //when
47 *   Result result = systemUnderTest.perform();
48 *
49 *   //then
50 *   assertEquals(failure, result);
51 * </code></pre>
52 * <p>
53 * One of the purposes of BDDMockito is also to show how to tailor the mocking syntax to a different programming style.
54 *
55 * @since 1.8.0
56 */
57@SuppressWarnings("unchecked")
58public class BDDMockito extends Mockito {
59
60    /**
61     * See original {@link OngoingStubbing}
62     * @since 1.8.0
63     */
64    public static interface BDDMyOngoingStubbing<T> {
65
66        /**
67         * See original {@link OngoingStubbing#thenAnswer(Answer)}
68         * @since 1.8.0
69         */
70        BDDMyOngoingStubbing<T> willAnswer(Answer<?> answer);
71
72        /**
73         * See original {@link OngoingStubbing#then(Answer)}
74         * @since 1.9.0
75         */
76        BDDMyOngoingStubbing<T> will(Answer<?> answer);
77
78        /**
79         * See original {@link OngoingStubbing#thenReturn(Object)}
80         * @since 1.8.0
81         */
82        BDDMyOngoingStubbing<T> willReturn(T value);
83
84        /**
85         * See original {@link OngoingStubbing#thenReturn(Object, Object[])}
86         * @since 1.8.0
87         */
88        BDDMyOngoingStubbing<T> willReturn(T value, T... values);
89
90        /**
91         * See original {@link OngoingStubbing#thenThrow(Throwable...)}
92         * @since 1.8.0
93         */
94        BDDMyOngoingStubbing<T> willThrow(Throwable... throwables);
95
96        /**
97         * See original {@link OngoingStubbing#thenThrow(Class[])}
98         * @since 1.9.0
99         */
100        BDDMyOngoingStubbing<T> willThrow(Class<? extends Throwable>... throwableClasses);
101
102        /**
103         * See original {@link OngoingStubbing#thenCallRealMethod()}
104         * @since 1.9.0
105         */
106        BDDMyOngoingStubbing<T> willCallRealMethod();
107
108        /**
109         * See original {@link OngoingStubbing#getMock()}
110         * @since 1.9.0
111         */
112        <M> M getMock();
113    }
114
115    public static class BDDOngoingStubbingImpl<T> implements BDDMyOngoingStubbing<T> {
116
117        private final OngoingStubbing<T> mockitoOngoingStubbing;
118
119        public BDDOngoingStubbingImpl(OngoingStubbing<T> ongoingStubbing) {
120            this.mockitoOngoingStubbing = ongoingStubbing;
121        }
122
123        /* (non-Javadoc)
124         * @see BDDMockito.BDDMyOngoingStubbing#willAnswer(Answer)
125         */
126        public BDDMyOngoingStubbing<T> willAnswer(Answer<?> answer) {
127            return new BDDOngoingStubbingImpl<T>(mockitoOngoingStubbing.thenAnswer(answer));
128        }
129
130        /* (non-Javadoc)
131         * @see BDDMockito.BDDMyOngoingStubbing#will(Answer)
132         */
133        public BDDMyOngoingStubbing<T> will(Answer<?> answer) {
134            return new BDDOngoingStubbingImpl<T>(mockitoOngoingStubbing.then(answer));
135        }
136
137        /* (non-Javadoc)
138         * @see BDDMockito.BDDMyOngoingStubbing#willReturn(java.lang.Object)
139         */
140        public BDDMyOngoingStubbing<T> willReturn(T value) {
141            return new BDDOngoingStubbingImpl<T>(mockitoOngoingStubbing.thenReturn(value));
142        }
143
144        /* (non-Javadoc)
145         * @see BDDMockito.BDDMyOngoingStubbing#willReturn(java.lang.Object, T[])
146         */
147        public BDDMyOngoingStubbing<T> willReturn(T value, T... values) {
148            return new BDDOngoingStubbingImpl<T>(mockitoOngoingStubbing.thenReturn(value, values));
149        }
150
151        /* (non-Javadoc)
152         * @see BDDMockito.BDDMyOngoingStubbing#willThrow(java.lang.Throwable[])
153         */
154        public BDDMyOngoingStubbing<T> willThrow(Throwable... throwables) {
155            return new BDDOngoingStubbingImpl<T>(mockitoOngoingStubbing.thenThrow(throwables));
156        }
157        /* (non-Javadoc)
158         * @see BDDMockito.BDDMyOngoingStubbing#willThrow(java.lang.Class[])
159         */
160        public BDDMyOngoingStubbing<T> willThrow(Class<? extends Throwable>... throwableClasses) {
161            return new BDDOngoingStubbingImpl<T>(mockitoOngoingStubbing.thenThrow(throwableClasses));
162        }
163
164        public BDDMyOngoingStubbing<T> willCallRealMethod() {
165            return new BDDOngoingStubbingImpl<T>(mockitoOngoingStubbing.thenCallRealMethod());
166        }
167
168        public <M> M getMock() {
169            return (M) mockitoOngoingStubbing.getMock();
170        }
171    }
172
173    /**
174     * see original {@link Mockito#when(Object)}
175     * @since 1.8.0
176     */
177    public static <T> BDDMyOngoingStubbing<T> given(T methodCall) {
178        return new BDDOngoingStubbingImpl<T>(Mockito.when(methodCall));
179    }
180
181    /**
182     * See original {@link Stubber}
183     * @since 1.8.0
184     */
185    public static interface BDDStubber {
186        /**
187         * See original {@link Stubber#doAnswer(Answer)}
188         * @since 1.8.0
189         */
190        BDDStubber willAnswer(Answer answer);
191
192        /**
193         * See original {@link Stubber#doNothing()}
194         * @since 1.8.0
195         */
196        BDDStubber willNothing();
197
198        /**
199         * See original {@link Stubber#doReturn(Object)}
200         * @since 1.8.0
201         */
202        BDDStubber willReturn(Object toBeReturned);
203
204        /**
205         * See original {@link Stubber#doThrow(Throwable)}
206         * @since 1.8.0
207         */
208        BDDStubber willThrow(Throwable toBeThrown);
209
210        /**
211         * See original {@link Stubber#doThrow(Class)}
212         * @since 1.9.0
213         */
214        BDDStubber willThrow(Class<? extends Throwable> toBeThrown);
215
216        /**
217         * See original {@link Stubber#doCallRealMethod()}
218         * @since 1.9.0
219         */
220        BDDStubber willCallRealMethod();
221
222        /**
223         * See original {@link Stubber#when(Object)}
224         * @since 1.8.0
225         */
226        <T> T given(T mock);
227    }
228
229    public static class BDDStubberImpl implements BDDStubber {
230
231        private final Stubber mockitoStubber;
232
233        public BDDStubberImpl(Stubber mockitoStubber) {
234            this.mockitoStubber = mockitoStubber;
235        }
236
237        /* (non-Javadoc)
238         * @see BDDMockito.BDDStubber#given(java.lang.Object)
239         */
240        public <T> T given(T mock) {
241            return mockitoStubber.when(mock);
242        }
243
244        /* (non-Javadoc)
245         * @see BDDMockito.BDDStubber#willAnswer(Answer)
246         */
247        public BDDStubber willAnswer(Answer answer) {
248            return new BDDStubberImpl(mockitoStubber.doAnswer(answer));
249        }
250
251        /* (non-Javadoc)
252         * @see BDDMockito.BDDStubber#willNothing()
253         */
254        public BDDStubber willNothing() {
255            return new BDDStubberImpl(mockitoStubber.doNothing());
256        }
257
258        /* (non-Javadoc)
259         * @see BDDMockito.BDDStubber#willReturn(java.lang.Object)
260         */
261        public BDDStubber willReturn(Object toBeReturned) {
262            return new BDDStubberImpl(mockitoStubber.doReturn(toBeReturned));
263        }
264
265        /* (non-Javadoc)
266         * @see BDDMockito.BDDStubber#willThrow(java.lang.Throwable)
267         */
268        public BDDStubber willThrow(Throwable toBeThrown) {
269            return new BDDStubberImpl(mockitoStubber.doThrow(toBeThrown));
270        }
271
272        /* (non-Javadoc)
273         * @see BDDMockito.BDDStubber#willThrow(Class)
274         */
275        public BDDStubber willThrow(Class<? extends Throwable> toBeThrown) {
276            return new BDDStubberImpl(mockitoStubber.doThrow(toBeThrown));
277        }
278
279        /* (non-Javadoc)
280         * @see BDDMockito.BDDStubber#willCallRealMethod()
281         */
282        public BDDStubber willCallRealMethod() {
283            return new BDDStubberImpl(mockitoStubber.doCallRealMethod());
284        }
285    }
286
287    /**
288     * see original {@link Mockito#doThrow(Throwable)}
289     * @since 1.8.0
290     */
291    public static BDDStubber willThrow(Throwable toBeThrown) {
292        return new BDDStubberImpl(Mockito.doThrow(toBeThrown));
293    }
294
295    /**
296     * see original {@link Mockito#doThrow(Throwable)}
297     * @since 1.9.0
298     */
299    public static BDDStubber willThrow(Class<? extends Throwable> toBeThrown) {
300        return new BDDStubberImpl(Mockito.doThrow(toBeThrown));
301    }
302
303    /**
304     * see original {@link Mockito#doAnswer(Answer)}
305     * @since 1.8.0
306     */
307    public static BDDStubber willAnswer(Answer answer) {
308        return new BDDStubberImpl(Mockito.doAnswer(answer));
309    }
310
311    /**
312     * see original {@link Mockito#doNothing()}
313     * @since 1.8.0
314     */
315    public static BDDStubber willDoNothing() {
316        return new BDDStubberImpl(Mockito.doNothing());
317    }
318
319    /**
320     * see original {@link Mockito#doReturn(Object)}
321     * @since 1.8.0
322     */
323    public static BDDStubber willReturn(Object toBeReturned) {
324        return new BDDStubberImpl(Mockito.doReturn(toBeReturned));
325    }
326
327    /**
328     * see original {@link Mockito#doCallRealMethod()}
329     * @since 1.8.0
330     */
331    public static BDDStubber willCallRealMethod() {
332        return new BDDStubberImpl(Mockito.doCallRealMethod());
333    }
334}
335