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