View Javadoc

1   /*
2    * Copyright 2006-2008 The Kuali Foundation
3    * 
4    * Licensed under the Educational Community 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.opensource.org/licenses/ecl2.php
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 org.kuali.rice.kns.util;
17  
18  /**
19   * This class contains utility methods for making assertions in production code (not test code).
20   * Kuali is not using the {@code assert} keyword because those assertions
21   * are not enabled by default. We can use the methods of this class instead, or throw {@link AssertionError} directly. This makes
22   * assertions effective in production and development, and avoids any risk of changes to functionality because any side-effects that
23   * might be involved in the assertion are done consistently. Although {@code AssertionError} can be thrown directly, and sometimes
24   * the compiler requires this, in many cases these method invocations will be easier to read than the extra {@code if} block with
25   * its negated conditional.
26   * 
27   * <p/> These assertions are for use in production code. They should not be confused with
28   * {@link junit.framework.Assert}, {@link junit.framework.AssertionFailedError}, nor {@link org.kuali.test.util.KualiTestAssertionUtils},
29   * which are for test code.
30   * 
31   * <p/> These methods
32   * should be used such that when they fail and throw {@code AssertionError}, it indicates that there is a bug in our software.
33   * Drawing attention to the bug this way, as soon as it's discovered, reduces the amount of work required to fix it. So, we should
34   * not catch {@code AssertionError} (or {@link Throwable}) and try to handle or work around it; it indicates a need to change some
35   * source code so that the assertion is never false. For more about why, when, and how to use assertions, see <a
36   * href="https://test.kuali.org/confluence/display/KULDEV/Assert+Keyword+And+AssertionError">Kuali's guide to assertions</a> and <a
37   * href="http://java.sun.com/j2se/1.4.2/docs/guide/lang/assert.html">Sun's guide to assertions</a>.
38   * 
39   * @see org.kuali.test.util.KualiTestAssertionUtils
40   */
41  public class AssertionUtils {
42  
43      /**
44       * Asserts that the {@code isTrue} parameter is true. If this assertion fails, the {@code AssertionError} it throws will have no
45       * detail message, only a stacktrace indicating the source file and line number containing the assertion that failed. <p/> This
46       * method's name is intended to avoid confusion with JUnit asserts (which are for test code, not production code), and its
47       * signature is intended to resemble that of the {@code assert} keyword.
48       * 
49       * @param isTrue whether this assertion succeeds. (Boolean objects are auto-unboxed by JDK 1.5.)
50       * 
51       * @throws AssertionError if {@code isTrue} is false
52       */
53      public static void assertThat(boolean isTrue) {
54          if (!isTrue) {
55              throw new AssertionError();
56          }
57      }
58  
59      /**
60       * Asserts that the {@code isTrue} parameter is true, with a detail message. The purpose of the detail message is to capture and
61       * communicate details about the assertion failure that will help a developer diagnose and fix the bug that led this assertion
62       * to fail. It's meant to be interpreted in the context of a full stack trace and with the source code containing the failed
63       * assertion. It is <em>not</em> a user-level error message. Details like {@code "assertion failed"} are redundant, not
64       * useful. <p/> This method's name is intended to avoid confusion with JUnit asserts (which are for test code, not production
65       * code), and its signature is intended to resemble that of the {@code assert} keyword.
66       * 
67       * @param isTrue whether this assertion succeeds. (Boolean objects are auto-unboxed by JDK 1.5.)
68       * 
69       * @param detailMessage value to use for the {@code AssertionError}'s detail message. If this is an instance of
70       *        {@link Throwable}, then it also becomes the {@code AssertionError}'s cause. (Primitives are auto-boxed by JDK 1.5.)
71       *        Objects are converted {@link Object#toString toString}, but only if this assertion fails, so it's better not to
72       *        convert this detail in advance. The code will be a little easier to read, and there will be some performance
73       *        improvement (altho it may be insignificant). For example, passing just {@code accountingLine} is better than passing
74       *        {@code accountingLine.toString()} or {@code "accounting line:"+accountingLine}. Since the assertion has failed, any
75       *        inconsistent side-effects from the conversion are not an issue. A {@code null} reference is treated as the String
76       *        {@code "null"}.
77       * 
78       * @throws AssertionError if {@code isTrue} is false
79       */
80      public static void assertThat(boolean isTrue, Object detailMessage) {
81          if (!isTrue) {
82              throw new AssertionError(detailMessage);
83          }
84      }
85  
86      /**
87       * Asserts that the {@code isTrue} parameter is true. This method is convenient for formatting the detail message, and as an
88       * optimization for detail arguments that are expensive to convert to String. For example, suppose {@code foo} and {@code bar}
89       * are two objects with expensive {@link Object#toString} methods. If you use
90       * 
91       * <pre>
92       * AssertionUtils.assertThat(foo.equals(bar), &quot;foo: &quot; + foo + &quot; bar: &quot; + bar);
93       * </pre>
94       * 
95       * then both object's {@code toString} methods will be invoked every time this assertion is done, even though those details are
96       * not normally needed because this assertion normally succeeds. You can use this method instead to only do those
97       * {@code toString} invocations if this assertion fails:
98       * 
99       * <pre>
100      * AssertionUtils.assertThat(foo.equals(bar), &quot;foo: %s bar: %s&quot;, foo, bar);
101      * </pre>
102      * 
103      * <p/> This method's name is intended to avoid confusion with JUnit asserts (which are for test code, not production code).
104      * 
105      * @param isTrue whether this assertion succeeds. (Boolean objects are auto-unboxed by JDK 1.5.)
106      * 
107      * @param detailMessageFormat a {@linkplain String#format format string} to be used in constructing the {@code AssertionError}'s
108      *        detail message. The purpose of this message is to capture and communicate details about the assertion failure that
109      *        will help a developer diagnose and fix the bug that led the assertion to fail. It's meant to be interpreted in the
110      *        context of a full stack trace and with the source code containing the failed assertion. It is <em>not</em> a
111      *        user-level error message. Details like {@code "assertion failed"} are redundant, not useful. This detail message
112      *        cannot be {@code null}.
113      * 
114      * @param detailMessageArgs one or more arguments to the format string. Nulls are allowed by some format conversions, such as
115      *        {@code "%s"}. (Primitives are auto-boxed by JDK 1.5.) Zero arguments will invoke {@link #assertThat(boolean, Object)}
116      *        instead, so the detail message will not be treated as a format string.
117      * 
118      * @throws AssertionError if {@code isTrue} is false
119      * 
120      * @throws java.util.IllegalFormatException if {@code detailMessageFormat} contains an illegal syntax, a format specifier that
121      *         is incompatible with the given arguments, insufficient arguments given the format string, or other illegal
122      *         conditions. For specification of all possible formatting errors, see the Details section of
123      *         {@link java.util.Formatter}.
124      * 
125      * @throws NullPointerException if the {@code detailMessageFormat} is {@code null}
126      * 
127      * @see String#format
128      */
129     public static void assertThat(boolean isTrue, String detailMessageFormat, Object... detailMessageArgs) {
130         if (!isTrue) {
131             throw new AssertionError(String.format(detailMessageFormat, detailMessageArgs));
132         }
133     }
134 }