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.debugging;
6 
7 import org.assertj.core.api.Assertions;
8 import org.junit.After;
9 import org.junit.Before;
10 import org.junit.Test;
11 import org.junit.runner.RunWith;
12 import org.mockito.Mock;
13 import org.mockito.internal.util.MockUtil;
14 import org.mockito.junit.MockitoJUnitRunner;
15 
16 import java.io.ByteArrayOutputStream;
17 import java.io.PrintStream;
18 
19 import static org.junit.Assert.fail;
20 import static org.mockito.BDDMockito.given;
21 import static org.mockito.Mockito.*;
22 
23 /**
24  * Tests the verbose logging of invocation on mock methods.
25  *
26  * BEWARE: These tests rely on mocking the standard output. While in a
27  * single-threaded environment the Before/After-contract ensures, that the
28  * original output stream is restored, there is no guarantee for this
29  * in the parallel setting.
30  * Maybe, the test class should be @Ignore'd by default ...
31  */
32 @RunWith(MockitoJUnitRunner.class)
33 public class VerboseLoggingOfInvocationsOnMockTest {
34 
35     private ByteArrayOutputStream output;
36     private PrintStream original;
37 
38     @Mock UnrelatedClass unrelatedMock;
39 
40     @Before
setUp()41     public void setUp() {
42         original = System.out;
43         output = new ByteArrayOutputStream();
44         System.setOut(new PrintStream(output));
45     }
46 
47     @After
tearDown()48     public void tearDown() {
49         System.setOut(original);
50     }
51 
52     @Test
shouldNotPrintInvocationOnMockWithoutSetting()53     public void shouldNotPrintInvocationOnMockWithoutSetting() {
54         // given
55         Foo foo = mock(Foo.class, withSettings().verboseLogging());
56 
57         // when
58         foo.giveMeSomeString("Klipsch");
59         unrelatedMock.unrelatedMethod("Apple");
60 
61         // then
62         Assertions.assertThat(printed())
63                 .doesNotContain(mockName(unrelatedMock))
64                 .doesNotContain("unrelatedMethod")
65                 .doesNotContain("Apple");
66     }
67 
68     @Test
shouldPrintUnstubbedInvocationOnMockToStdOut()69     public void shouldPrintUnstubbedInvocationOnMockToStdOut() {
70         // given
71         Foo foo = mock(Foo.class, withSettings().verboseLogging());
72 
73         // when
74         foo.doSomething("Klipsch");
75 
76         // then
77         Assertions.assertThat(printed())
78                 .contains(getClass().getName())
79                 .contains(mockName(foo))
80                 .contains("doSomething")
81                 .contains("Klipsch");
82     }
83 
84     @Test
shouldPrintStubbedInvocationOnMockToStdOut()85     public void shouldPrintStubbedInvocationOnMockToStdOut() {
86         // given
87         Foo foo = mock(Foo.class, withSettings().verboseLogging());
88         given(foo.giveMeSomeString("Klipsch")).willReturn("earbuds");
89 
90         // when
91         foo.giveMeSomeString("Klipsch");
92 
93         // then
94         Assertions.assertThat(printed())
95                 .contains(getClass().getName())
96                 .contains(mockName(foo))
97                 .contains("giveMeSomeString")
98                 .contains("Klipsch")
99                 .contains("earbuds");
100     }
101 
102     @Test
shouldPrintThrowingInvocationOnMockToStdOut()103     public void shouldPrintThrowingInvocationOnMockToStdOut() {
104         // given
105         Foo foo = mock(Foo.class, withSettings().verboseLogging());
106         doThrow(new ThirdPartyException()).when(foo).doSomething("Klipsch");
107 
108         try {
109             // when
110             foo.doSomething("Klipsch");
111             fail("Exception excepted.");
112         } catch (ThirdPartyException e) {
113             // then
114             Assertions.assertThat(printed())
115                     .contains(getClass().getName())
116                     .contains(mockName(foo))
117                     .contains("doSomething")
118                     .contains("Klipsch")
119                     .contains(ThirdPartyException.class.getName());
120         }
121     }
122 
123     @Test
shouldPrintRealInvocationOnSpyToStdOut()124     public void shouldPrintRealInvocationOnSpyToStdOut() {
125         // given
126         FooImpl fooSpy = mock(FooImpl.class,
127                 withSettings().spiedInstance(new FooImpl()).verboseLogging());
128         doCallRealMethod().when(fooSpy).doSomething("Klipsch");
129 
130         // when
131         fooSpy.doSomething("Klipsch");
132 
133         // then
134         Assertions.assertThat(printed())
135                 .contains(getClass().getName())
136                 .contains(mockName(fooSpy))
137                 .contains("doSomething")
138                 .contains("Klipsch");
139     }
140 
141     @Test
usage()142     public void usage() {
143         // given
144         Foo foo = mock(Foo.class, withSettings().verboseLogging());
145         given(foo.giveMeSomeString("Apple")).willReturn(
146                 "earbuds");
147 
148         // when
149         foo.giveMeSomeString("Shure");
150         foo.giveMeSomeString("Apple");
151         foo.doSomething("Klipsch");
152     }
153 
printed()154     private String printed() {
155         return output.toString();
156     }
157 
mockName(Object mock)158     private String mockName(Object mock) {
159         return MockUtil.getMockName(mock).toString();
160     }
161 
162     private static class UnrelatedClass {
unrelatedMethod(String anotherStringValue)163         void unrelatedMethod(String anotherStringValue) {
164         }
165     }
166 
167     /**
168      * An exception that isn't defined by Mockito or the JDK and therefore does
169      * not appear in the logging result by chance alone.
170      */
171     static class ThirdPartyException extends RuntimeException {
172         private static final long serialVersionUID = 2160445705646210847L;
173     }
174 
175     static class FooImpl implements Foo {
giveMeSomeString(String param)176         public String giveMeSomeString(String param) {
177             return null;
178         }
179 
doSomething(String param)180         public void doSomething(String param) {
181         }
182     }
183 }
184