1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 package org.chromium.chrome.browser.feed.library.common.testing;
6 
7 import static com.google.common.truth.ExpectFailure.assertThat;
8 import static com.google.common.truth.Truth.assertThat;
9 
10 import static org.mockito.Mockito.mock;
11 import static org.mockito.Mockito.verify;
12 import static org.mockito.Mockito.verifyNoMoreInteractions;
13 
14 import static org.chromium.chrome.browser.feed.library.common.testing.RunnableSubject.assertThatRunnable;
15 import static org.chromium.chrome.browser.feed.library.common.testing.RunnableSubject.runnables;
16 
17 import com.google.common.truth.ExpectFailure;
18 import com.google.common.truth.Truth;
19 
20 import org.junit.ComparisonFailure;
21 import org.junit.Rule;
22 import org.junit.Test;
23 import org.junit.runner.RunWith;
24 import org.junit.runners.JUnit4;
25 
26 import org.chromium.chrome.browser.feed.library.common.testing.RunnableSubject.ThrowingRunnable;
27 
28 import java.io.IOException;
29 import java.util.concurrent.ExecutionException;
30 
31 /** Unit tests for {@link RunnableSubject}. */
32 @RunWith(JUnit4.class)
33 public class RunnableSubjectTest {
34     @Rule
35     public final ExpectFailure expectFailure = new ExpectFailure();
36 
37     @Test
runToCompletion()38     public void runToCompletion() throws Throwable {
39         ThrowingRunnable run = mock(ThrowingRunnable.class);
40 
41         expectFailure.whenTesting()
42                 .about(runnables())
43                 .that(run)
44                 .throwsAnExceptionOfType(RuntimeException.class);
45 
46         verify(run).run();
47         AssertionError failure = expectFailure.getFailure();
48         assertThat(failure).factValue("expected to throw").isEqualTo("java.lang.RuntimeException");
49         assertThat(failure).factKeys().contains("but ran to completion");
50         verifyNoMoreInteractions(run);
51     }
52 
53     @Test
nullSubjectFailsEvenWhenExpectingNullRefException()54     public void nullSubjectFailsEvenWhenExpectingNullRefException() {
55         expectFailure.whenTesting()
56                 .about(runnables())
57                 .that(null)
58                 .throwsAnExceptionOfType(NullPointerException.class);
59 
60         AssertionError failure = expectFailure.getFailure();
61         assertThat(failure)
62                 .factValue("expected to throw")
63                 .isEqualTo("java.lang.NullPointerException");
64         assertThat(failure).factKeys().contains("but didn't run because it's null");
65     }
66 
67     @Test
wrongException()68     public void wrongException() {
69         expectFailure.whenTesting()
70                 .about(runnables())
71                 .that(() -> { throw new IllegalArgumentException("a"); })
72                 .throwsAnExceptionOfType(NullPointerException.class);
73 
74         AssertionError failure = expectFailure.getFailure();
75         assertThat(failure).factValue("value of").isEqualTo("runnable.thrownException()");
76         assertThat(failure)
77                 .factValue("expected instance of")
78                 .isEqualTo("java.lang.NullPointerException");
79         assertThat(failure)
80                 .factValue("but was instance of")
81                 .isEqualTo("java.lang.IllegalArgumentException");
82         assertThat(failure)
83                 .factValue("with value")
84                 .isEqualTo("java.lang.IllegalArgumentException: a");
85     }
86 
87     @Test
correctException()88     public void correctException() {
89         IllegalArgumentException ex = new IllegalArgumentException("b");
90 
91         Truth.assertAbout(runnables())
92                 .that(() -> { throw ex; })
93                 .throwsAnExceptionOfType(IllegalArgumentException.class)
94                 .that()
95                 .isSameInstanceAs(ex);
96     }
97 
98     @Test
wrongMessage()99     public void wrongMessage() {
100         expectFailure.whenTesting()
101                 .about(runnables())
102                 .that(() -> { throw new IOException("Wrong message!"); })
103                 .throwsAnExceptionOfType(IOException.class)
104                 .that()
105                 .hasMessageThat()
106                 .isEqualTo("Expected message.");
107 
108         ComparisonFailure failure = (ComparisonFailure) expectFailure.getFailure();
109         assertThat(failure.getExpected()).isEqualTo("Expected message.");
110         assertThat(failure.getActual()).isEqualTo("Wrong message!");
111     }
112 
113     @Test
correctMessage()114     public void correctMessage() {
115         String expectedMessage = "Expected message.";
116 
117         Truth.assertAbout(runnables())
118                 .that(() -> { throw new IOException(expectedMessage); })
119                 .throwsAnExceptionOfType(IOException.class)
120                 .that()
121                 .hasMessageThat()
122                 .isEqualTo(expectedMessage);
123     }
124 
125     @Test
getCaught()126     public void getCaught() {
127         IllegalArgumentException cause = new IllegalArgumentException("boo");
128         IOException ex = new IOException(cause);
129 
130         IOException caught = RunnableSubject.assertThat(() -> { throw ex; })
131                                      .throwsAnExceptionOfType(IOException.class)
132                                      .getCaught();
133         assertThat(caught).isSameInstanceAs(ex);
134     }
135 
136     @Test
wrongCauseType()137     public void wrongCauseType() {
138         IllegalArgumentException cause = new IllegalArgumentException("boo");
139         IOException ex = new IOException(cause);
140         expectFailure.whenTesting()
141                 .about(runnables())
142                 .that(() -> { throw ex; })
143                 .throwsAnExceptionOfType(IOException.class)
144                 .causedByAnExceptionOfType(ExecutionException.class);
145         AssertionError failure = expectFailure.getFailure();
146         assertThat(failure)
147                 .factValue("value of")
148                 .isEqualTo("runnable.thrownException().getCause()");
149         assertThat(failure)
150                 .factValue("expected instance of")
151                 .isEqualTo("java.util.concurrent.ExecutionException");
152         assertThat(failure)
153                 .factValue("but was instance of")
154                 .isEqualTo("java.lang.IllegalArgumentException");
155         assertThat(failure)
156                 .factValue("with value")
157                 .isEqualTo("java.lang.IllegalArgumentException: boo");
158     }
159 
160     @Test
correctCauseType()161     public void correctCauseType() {
162         IllegalArgumentException cause = new IllegalArgumentException("boo");
163         IOException ex = new IOException(cause);
164 
165         Truth.assertAbout(runnables())
166                 .that(() -> { throw ex; })
167                 .throwsAnExceptionOfType(IOException.class)
168                 .causedByAnExceptionOfType(IllegalArgumentException.class)
169                 .that()
170                 .hasMessageThat()
171                 .isEqualTo("boo");
172     }
173 
174     @Test
causedByCorrect()175     public void causedByCorrect() {
176         IOException cause = new IOException();
177         IllegalArgumentException ex = new IllegalArgumentException(cause);
178 
179         Truth.assertAbout(runnables())
180                 .that(() -> { throw ex; })
181                 .throwsAnExceptionOfType(IllegalArgumentException.class)
182                 .causedBy(cause);
183     }
184 
185     @Test
causedByWrong()186     public void causedByWrong() {
187         IOException cause = new IOException();
188         IllegalArgumentException ex = new IllegalArgumentException(cause);
189 
190         expectFailure.whenTesting()
191                 .about(runnables())
192                 .that(() -> { throw ex; })
193                 .throwsAnExceptionOfType(IllegalArgumentException.class)
194                 .causedBy(new IOException());
195     }
196 
197     @Test
exampleUsage()198     public void exampleUsage() {
199         assertThatRunnable(() -> { throw new IOException("boo!"); })
200                 .throwsAnExceptionOfType(IOException.class)
201                 .that()
202                 .hasMessageThat()
203                 .isEqualTo("boo!");
204 
205         RunnableSubject.assertThat(() -> { throw new IllegalArgumentException("oh no"); })
206                 .throwsAnExceptionOfType(IllegalArgumentException.class)
207                 .that()
208                 .hasMessageThat()
209                 .isEqualTo("oh no");
210 
211         RunnableSubject
212                 .assertThat(() -> {
213                     throw new IllegalArgumentException(new RuntimeException("glitch"));
214                 })
215                 .throwsAnExceptionOfType(IllegalArgumentException.class)
216                 .causedByAnExceptionOfType(RuntimeException.class)
217                 .that()
218                 .hasMessageThat()
219                 .isEqualTo("glitch");
220 
221         // Recursive self-verification.
222         RunnableSubject
223                 .assertThat(()
224                                     -> RunnableSubject.assertThat(() -> {}).throwsAnExceptionOfType(
225                                             RuntimeException.class))
226                 .throwsAnExceptionOfType(AssertionError.class);
227     }
228 }
229