Coverage Report - org.truth0.subjects.Subject
 
Classes in this File Line Coverage Branch Coverage Complexity
Subject
94%
64/68
100%
30/30
2.444
Subject$1
0%
0/3
N/A
2.444
Subject$2
0%
0/3
N/A
2.444
Subject$3
62%
10/16
66%
4/6
2.444
Subject$HasField
N/A
N/A
2.444
 
 1  
 /*
 2  
  * Copyright (c) 2011 David Saff
 3  
  * Copyright (c) 2011 Christian Gruber
 4  
  *
 5  
  * Licensed under the Apache License, Version 2.0 (the "License");
 6  
  * you may not use this file except in compliance with the License.
 7  
  * You may obtain a copy of the License at
 8  
  *
 9  
  * http://www.apache.org/licenses/LICENSE-2.0
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 package org.truth0.subjects;
 18  
 
 19  
 
 20  
 import java.lang.reflect.Field;
 21  
 
 22  
 import org.truth0.FailureStrategy;
 23  
 import org.truth0.TestVerb;
 24  
 import org.truth0.util.ReflectionUtil;
 25  
 
 26  
 import com.google.common.annotations.GwtCompatible;
 27  
 import com.google.common.annotations.GwtIncompatible;
 28  
 
 29  
 /**
 30  
  * Propositions for arbitrarily typed subjects and for properties
 31  
  * of Object
 32  
  *
 33  
  * @author David Saff
 34  
  * @author Christian Gruber (cgruber@israfil.net)
 35  
  */
 36  
 @GwtCompatible(emulated = true)
 37  
 public class Subject<S extends Subject<S,T>,T> {
 38  
   protected final FailureStrategy failureStrategy;
 39  
   private final T subject;
 40  
 
 41  324
   public Subject(FailureStrategy failureStrategy, T subject) {
 42  324
     this.failureStrategy = failureStrategy;
 43  324
     this.subject = subject;
 44  324
   }
 45  
 
 46  
   public void is(T other) {
 47  
 
 48  17
     if (getSubject() == null) {
 49  2
       if(other != null) {
 50  1
         fail("is", other);
 51  
       }
 52  
     } else {
 53  15
       if (!getSubject().equals(other)) {
 54  1
         fail("is", other);
 55  
       }
 56  
     }
 57  15
   }
 58  
 
 59  
   public void isNull() {
 60  2
     if (getSubject() != null) {
 61  1
       failWithoutSubject("is null");
 62  
     }
 63  1
   }
 64  
 
 65  
   public void isNotNull() {
 66  3
     if (getSubject() == null) {
 67  1
       failWithoutSubject("is not null");
 68  
     }
 69  2
   }
 70  
 
 71  
   public void isEqualTo(Object other) {
 72  21
     if (getSubject() == null) {
 73  3
       if(other != null) {
 74  2
         fail("is equal to", other);
 75  
       }
 76  
     } else {
 77  18
       if (!getSubject().equals(other)) {
 78  3
         fail("is equal to", other);
 79  
       }
 80  
     }
 81  16
   }
 82  
 
 83  
   public void isNotEqualTo(Object other) {
 84  6
     if (getSubject() == null) {
 85  2
       if(other == null) {
 86  1
         fail("is not equal to", (Object)null);
 87  
       }
 88  
     } else {
 89  4
       if (getSubject().equals(other)) {
 90  2
         fail("is not equal to", other);
 91  
       }
 92  
     }
 93  3
   }
 94  
 
 95  
   @GwtIncompatible("Class.isInstance")
 96  
   public void isA(Class<?> clazz) {
 97  2
     if (!clazz.isInstance(getSubject())) {
 98  1
       fail("is a", clazz.getName());
 99  
     }
 100  1
   }
 101  
 
 102  
   @GwtIncompatible("Class.isInstance")
 103  
   public void isNotA(Class<?> clazz) {
 104  2
     if (clazz.isInstance(getSubject())) {
 105  1
       fail("is not a", clazz.getName());
 106  
     }
 107  1
   }
 108  
 
 109  
   protected T getSubject() {
 110  603
     return subject;
 111  
   }
 112  
 
 113  
   protected TestVerb check() {
 114  0
     return new TestVerb(failureStrategy);
 115  
   }
 116  
 
 117  
   /**
 118  
    * Assembles a failure message and passes such to the FailureStrategy
 119  
    * @param verb the act being asserted
 120  
    * @param messageParts the expectations against which the subject is compared
 121  
    */
 122  
   protected void fail(String verb, Object... messageParts) {
 123  68
     StringBuilder message = new StringBuilder("Not true that ");
 124  68
     message.append("<").append(getSubject()).append("> ").append(verb);
 125  144
     for (Object part : messageParts) {
 126  76
       message.append(" <").append(part).append(">");
 127  
     }
 128  68
     failureStrategy.fail(message.toString());
 129  6
   }
 130  
 
 131  
   /**
 132  
    * Assembles a failure message and passes such to the FailureStrategy
 133  
    * @param verb the act being asserted
 134  
    * @param messageParts the expectations against which the subject is compared
 135  
    */
 136  
   protected void failWithBadResults(String verb, Object expected, String failVerb, Object actual) {
 137  5
     StringBuilder message = new StringBuilder("Not true that ");
 138  5
     message.append("<").append(getSubject()).append("> ").append(verb);
 139  5
     message.append(" <").append(expected).append(">");
 140  5
     message.append(" it ").append(failVerb);
 141  5
     message.append(" <").append(actual).append(">");
 142  5
     failureStrategy.fail(message.toString());
 143  1
   }
 144  
 
 145  
   protected void failWithoutSubject(String verb) {
 146  2
     StringBuilder message = new StringBuilder("Not true that ");
 147  2
     message.append("the subject ").append(verb);
 148  2
     failureStrategy.fail(message.toString());
 149  0
   }
 150  
 
 151  
   @GwtIncompatible("java.lang.reflect.Field")
 152  
   public HasField hasField(final String fieldName) {
 153  10
     final T subject = getSubject();
 154  10
     if (subject == null) {
 155  1
       failureStrategy.fail("Cannot determine a field name from a null object.");
 156  
       // Needed for Expect and other non-terminal failure strategies
 157  0
       return new HasField() {
 158  
         @Override public void withValue(Object value) {
 159  0
           Subject.this.fail("Cannot test the presence of a value in a null object.");
 160  0
         }
 161  
       };
 162  
     }
 163  9
     final Class<?> subjectClass = subject.getClass();
 164  
     final Field field;
 165  
     try {
 166  9
       field = ReflectionUtil.getField(subjectClass, fieldName);
 167  7
       field.setAccessible(true);
 168  2
     } catch (NoSuchFieldException e) {
 169  2
       StringBuilder message = new StringBuilder("Not true that ");
 170  2
       message.append("<").append(subjectClass.getSimpleName()).append(">");
 171  2
       message.append(" has a field named <").append(fieldName).append(">");
 172  2
       failureStrategy.fail(message.toString());
 173  
 
 174  
       // Needed for Expect and other non-terminal failure strategies
 175  0
       return new HasField() {
 176  
         @Override public void withValue(Object value) {
 177  0
           Subject.this.fail("Cannot test the presence of a value in a non-present field.");
 178  0
         }
 179  
       };
 180  7
     }
 181  7
     return new HasField() {
 182  
       @Override public void withValue(Object expected) {
 183  
         try {
 184  5
           Object actual = field.get(subject);
 185  5
           if (expected == actual || (expected != null && expected.equals(actual))) {
 186  3
             return;
 187  
           } else {
 188  2
             StringBuilder message = new StringBuilder("Not true that ");
 189  2
             message.append("<").append(subjectClass.getSimpleName()).append(">'s");
 190  2
             message.append(" field <").append(fieldName).append(">");
 191  2
             message.append(" contains expected value <").append(expected).append(">.");
 192  2
             message.append(" It contains value <").append(actual).append(">");
 193  2
             failureStrategy.fail(message.toString());
 194  
           }
 195  0
         } catch (IllegalArgumentException e) {
 196  0
           throw new RuntimeException(
 197  
               "Error checking field " + fieldName + " while testing for value " + expected);
 198  0
         } catch (IllegalAccessException e) {
 199  0
           throw new RuntimeException(
 200  
               "Cannot access field " + fieldName + " to test for value " + expected);
 201  0
         }
 202  0
       }
 203  
     };
 204  
   }
 205  
 
 206  
   @GwtIncompatible("java.lang.reflect.Field")
 207  
   public static interface HasField {
 208  
     /**
 209  
      * Supplementary assertion in which a present field can be tested
 210  
      * to determine if it contains a given value.
 211  
      */
 212  
     void withValue(Object value);
 213  
   }
 214  
 
 215  
 }