• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2014 Google, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.google.common.truth;
17 
18 import org.checkerframework.checker.nullness.qual.Nullable;
19 
20 /**
21  * Propositions for {@link Throwable} subjects.
22  *
23  * @author Kurt Alfred Kluever
24  */
25 public class ThrowableSubject extends Subject {
26   private final Throwable actual;
27 
28   /**
29    * Constructor for use by subclasses. If you want to create an instance of this class itself, call
30    * {@link Subject#check(String, Object...) check(...)}{@code .that(actual)}.
31    */
ThrowableSubject(FailureMetadata metadata, @Nullable Throwable throwable)32   protected ThrowableSubject(FailureMetadata metadata, @Nullable Throwable throwable) {
33     this(metadata, throwable, null);
34   }
35 
ThrowableSubject( FailureMetadata metadata, @Nullable Throwable throwable, @Nullable String typeDescription)36   ThrowableSubject(
37       FailureMetadata metadata, @Nullable Throwable throwable, @Nullable String typeDescription) {
38     super(metadata, throwable, typeDescription);
39     this.actual = throwable;
40   }
41 
42   /*
43    * TODO(cpovirk): consider a special case for isEqualTo and isSameInstanceAs that adds |expected|
44    * as a suppressed exception
45    */
46 
47   /** Returns a {@code StringSubject} to make assertions about the throwable's message. */
hasMessageThat()48   public final StringSubject hasMessageThat() {
49     StandardSubjectBuilder check = check("getMessage()");
50     if (actual instanceof ErrorWithFacts && ((ErrorWithFacts) actual).facts().size() > 1) {
51       check =
52           check.withMessage(
53               "(Note from Truth: When possible, instead of asserting on the full message, assert"
54                   + " about individual facts by using ExpectFailure.assertThat.)");
55     }
56     return check.that(actual.getMessage());
57   }
58 
59   /**
60    * Returns a new {@code ThrowableSubject} that supports assertions on this throwable's direct
61    * cause. This method can be invoked repeatedly (e.g. {@code
62    * assertThat(e).hasCauseThat().hasCauseThat()....} to assert on a particular indirect cause.
63    */
hasCauseThat()64   public final ThrowableSubject hasCauseThat() {
65     // provides a more helpful error message if hasCauseThat() methods are chained too deep
66     // e.g. assertThat(new Exception()).hCT().hCT()....
67     // TODO(diamondm) in keeping with other subjects' behavior this should still NPE if the subject
68     // *itself* is null, since there's no context to lose. See also b/37645583
69     if (actual == null) {
70       check("getCause()")
71           .withMessage("Causal chain is not deep enough - add a .isNotNull() check?")
72           .fail();
73       return ignoreCheck()
74           .that(
75               new Throwable() {
76                 @Override
77                 public Throwable fillInStackTrace() {
78                   setStackTrace(new StackTraceElement[0]); // for old versions of Android
79                   return this;
80                 }
81               });
82     }
83     return check("getCause()").that(actual.getCause());
84   }
85 }
86