This is an automated email from the ASF dual-hosted git repository.

jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git


The following commit(s) were added to refs/heads/master by this push:
     new 106a9a0  Fluent assertion improvements.
106a9a0 is described below

commit 106a9a0c80f998585f9aaa25022188f58d49d9ef
Author: JamesBognar <james.bog...@salesforce.com>
AuthorDate: Tue Feb 16 17:35:56 2021 -0500

    Fluent assertion improvements.
---
 .../org/apache/juneau/assertions/Assertions.java   | 37 +++++++++++++----
 .../apache/juneau/assertions/BeanAssertion.java    | 16 ++++----
 .../juneau/assertions/FluentArrayAssertion.java    | 22 ++++++++++-
 .../juneau/assertions/FluentBaseAssertion.java     | 17 --------
 .../juneau/assertions/FluentBeanAssertion.java     | 43 +++++++++++++++-----
 .../juneau/assertions/FluentListAssertion.java     | 22 ++++++++++-
 .../juneau/assertions/FluentMapAssertion.java      | 28 ++++++++++++-
 .../juneau/assertions/FluentObjectAssertion.java   | 15 +++----
 .../assertions/FluentThrowableAssertion.java       | 46 ++++++++++++++++------
 .../apache/juneau/assertions/ObjectAssertion.java  | 18 +++++----
 .../juneau/assertions/ThrowableAssertion.java      | 18 +++++----
 .../apache/juneau/http/BasicNamedAttribute.java    |  2 +-
 .../apache/juneau/rest/client/ResponseBody.java    |  2 +-
 .../apache/juneau/rest/client/RestResponse.java    |  2 +-
 .../rest/logging/BasicTestCaptureRestLogger.java   |  4 +-
 .../juneau/assertions/ObjectAssertion_Test.java    |  4 +-
 .../juneau/assertions/ThrowableAssertion_Test.java |  7 ++--
 .../client/RestClient_Response_Headers_Test.java   |  1 -
 18 files changed, 211 insertions(+), 93 deletions(-)

diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/Assertions.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/Assertions.java
index 9e26969..8daac05 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/Assertions.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/Assertions.java
@@ -184,7 +184,7 @@ public class Assertions {
         * @param value The object being wrapped.
         * @return A new {@link ObjectAssertion} object.  Never <jk>null</jk>.
         */
-       public static ObjectAssertion assertObject(Object value) {
+       public static <V> ObjectAssertion<V> assertObject(V value) {
                return ObjectAssertion.create(value);
        }
 
@@ -200,7 +200,7 @@ public class Assertions {
         * @param value The object being wrapped.
         * @return A new {@link ObjectAssertion} object.  Never <jk>null</jk>.
         */
-       public static ObjectAssertion assertObject(Optional<?> value) {
+       public static <V> ObjectAssertion<V> assertObject(Optional<V> value) {
                assertArgNotNull("value", value);
                return assertObject(value.orElse(null));
        }
@@ -217,7 +217,7 @@ public class Assertions {
         * @param value The object being wrapped.
         * @return A new {@link BeanAssertion} object.  Never <jk>null</jk>.
         */
-       public static BeanAssertion assertBean(Object value) {
+       public static <V> BeanAssertion<V> assertBean(V value) {
                return BeanAssertion.create(value);
        }
 
@@ -233,7 +233,7 @@ public class Assertions {
         * @param value The object being wrapped.
         * @return A new {@link BeanAssertion} object.  Never <jk>null</jk>.
         */
-       public static BeanAssertion assertBean(Optional<?> value) {
+       public static <V> BeanAssertion<V> assertBean(Optional<V> value) {
                assertArgNotNull("value", value);
                return assertBean(value.orElse(null));
        }
@@ -316,7 +316,7 @@ public class Assertions {
         * @param value The throwable being wrapped.
         * @return A new {@link ThrowableAssertion} object.  Never 
<jk>null</jk>.
         */
-       public static ThrowableAssertion assertThrowable(Throwable value) {
+       public static <V extends Throwable> ThrowableAssertion<V> 
assertThrowable(V value) {
                return ThrowableAssertion.create(value);
        }
 
@@ -400,11 +400,34 @@ public class Assertions {
         * @param snippet The snippet of code to execute.
         * @return A new assertion object.  Never <jk>null</jk>.
         */
-       public static ThrowableAssertion assertThrown(Snippet snippet) {
+       public static ThrowableAssertion<Throwable> assertThrown(Snippet 
snippet) {
+               return assertThrown(Throwable.class, snippet);
+       }
+
+       /**
+        * Executes an arbitrary snippet of code and captures anything thrown 
from it.
+        *
+        * <h5 class='section'>Example:</h5>
+        * <p class='bcode w800'>
+        *      <jc>// Asserts that the specified method throws a 
RuntimeException containing "Foobar" in the message. </jc>
+        *      <jsm>assertThrown</jsm>(()-&gt;<jv>foo</jv>.getBar())
+        *              .exists()
+        *              .isType(RuntimeException.<jk>class</jk>)
+        *              .contains(<js>"Foobar"</js>);
+        * </p>
+        *
+        * @param type The expected exception type.
+        * @param snippet The snippet of code to execute.
+        * @return A new assertion object.  Never <jk>null</jk>.
+        */
+       @SuppressWarnings("unchecked")
+       public static <T extends Throwable> ThrowableAssertion<Throwable> 
assertThrown(Class<T> type, Snippet snippet) {
                try {
                        snippet.run();
                } catch (Throwable e) {
-                       return assertThrowable(e);
+                       if (type.isInstance(e))
+                               return assertThrowable((T)e);
+                       throw new BasicAssertionError("Exception not of 
expected type.\n\tExpected: {1}.\n\tActual: {2}", type, e.getClass());
                }
                return assertThrowable(null);
        }
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/BeanAssertion.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/BeanAssertion.java
index 60e3f3b..92282de 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/BeanAssertion.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/BeanAssertion.java
@@ -22,9 +22,11 @@ import org.apache.juneau.internal.*;
  *     <jc>// Validates the specified POJO is the specified type and 
serializes to the specified value.</jc>
  *     
<jsm>assertBean</jsm>(<jv>myBean</jv>).isType(MyBean.<jk>class</jk>).fields(<js>"foo"</js>).asJson().is(<js>"{foo:'bar'}"</js>);
  * </p>
+ *
+ * @param <V> The bean type.
  */
 @FluentSetters(returns="BeanAssertion")
-public class BeanAssertion extends FluentBeanAssertion<BeanAssertion> {
+public class BeanAssertion<V> extends 
FluentBeanAssertion<Object,BeanAssertion<V>> {
 
        /**
         * Creator.
@@ -32,8 +34,8 @@ public class BeanAssertion extends 
FluentBeanAssertion<BeanAssertion> {
         * @param value The object being wrapped.
         * @return A new {@link BeanAssertion} object.
         */
-       public static BeanAssertion create(Object value) {
-               return new BeanAssertion(value);
+       public static <V> BeanAssertion<V> create(V value) {
+               return new BeanAssertion<>(value);
        }
 
        /**
@@ -46,26 +48,26 @@ public class BeanAssertion extends 
FluentBeanAssertion<BeanAssertion> {
        }
 
        @Override
-       protected BeanAssertion returns() {
+       protected BeanAssertion<V> returns() {
                return this;
        }
 
        // <FluentSetters>
 
        @Override /* GENERATED - Assertion */
-       public BeanAssertion msg(String msg, Object...args) {
+       public BeanAssertion<V> msg(String msg, Object...args) {
                super.msg(msg, args);
                return this;
        }
 
        @Override /* GENERATED - Assertion */
-       public BeanAssertion stderr() {
+       public BeanAssertion<V> stderr() {
                super.stderr();
                return this;
        }
 
        @Override /* GENERATED - Assertion */
-       public BeanAssertion stdout() {
+       public BeanAssertion<V> stdout() {
                super.stdout();
                return this;
        }
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/FluentArrayAssertion.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/FluentArrayAssertion.java
index 3468ec9..c942d4b 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/FluentArrayAssertion.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/FluentArrayAssertion.java
@@ -134,8 +134,26 @@ public class FluentArrayAssertion<R> extends 
FluentBaseAssertion<Object,R> {
         * @param index The index of the item to retrieve from the array.
         * @return A new assertion.
         */
-       public FluentObjectAssertion<R> item(int index) {
-               return new FluentObjectAssertion<>(this, getItem(index), 
returns());
+       public FluentObjectAssertion<Object,R> item(int index) {
+               return item(Object.class, index);
+       }
+
+       /**
+        * Returns an object assertion on the item specified at the specified 
index.
+        *
+        * <p>
+        * If the array is <jk>null</jk> or the index is out-of-bounds, the 
returned assertion is a null assertion
+        * (meaning {@link FluentObjectAssertion#exists()} returns 
<jk>false</jk>).
+        *
+        * @param type The value type.
+        * @param index The index of the item to retrieve from the array.
+        * @return A new assertion.
+        */
+       public <V> FluentObjectAssertion<Object,R> item(Class<V> type, int 
index) {
+               Object v = getItem(index);
+               if (v == null || type.isInstance(v))
+                       return new FluentObjectAssertion<>(this, v, returns());
+               throw error("Array value not of expected type at index 
''{0}''.\n\tExpected: {1}.\n\tActual: {2}", index, type, v.getClass());
        }
 
        private Object getItem(int index) {
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/FluentBaseAssertion.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/FluentBaseAssertion.java
index 26dc70e..caf322e 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/FluentBaseAssertion.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/FluentBaseAssertion.java
@@ -303,23 +303,6 @@ public class FluentBaseAssertion<V,R> extends 
FluentAssertion<R> {
        }
 
        /**
-        * Asserts that the value passes the specified predicate test.
-        *
-        * @param c The class type of the object being tested.
-        * @param <T> The class type of the object being tested.
-        * @param test The predicate to use to test the value.
-        * @return The response object (for method chaining).
-        * @throws AssertionError If assertion failed.
-        */
-       @SuppressWarnings("unchecked")
-       public <T> R passes(Class<T> c, Predicate<T> test) throws 
AssertionError {
-               isType(c);
-               if (! test.test((T)value))
-                       throw error("Value did not pass predicate 
test.\n\tValue=[{0}]", value);
-               return returns();
-       }
-
-       /**
         * Asserts that the object is not null.
         *
         * <p>
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/FluentBeanAssertion.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/FluentBeanAssertion.java
index f4764fe..5c4623a 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/FluentBeanAssertion.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/FluentBeanAssertion.java
@@ -18,10 +18,11 @@ import org.apache.juneau.internal.*;
 /**
  * Used for fluent assertion calls against Java beans.
  *
+ * @param <V> The bean type.
  * @param <R> The return type.
  */
-@FluentSetters(returns="FluentObjectAssertion<R>")
-public class FluentBeanAssertion<R> extends FluentBaseAssertion<Object,R> {
+@FluentSetters(returns="FluentBeanAssertion<V,R>")
+public class FluentBeanAssertion<V,R> extends FluentBaseAssertion<Object,R> {
 
        private final Object value;
 
@@ -31,7 +32,7 @@ public class FluentBeanAssertion<R> extends 
FluentBaseAssertion<Object,R> {
         * @param value The object being tested.
         * @param returns The object to return after the test.
         */
-       public FluentBeanAssertion(Object value, R returns) {
+       public FluentBeanAssertion(V value, R returns) {
                this(null, value, returns);
        }
 
@@ -42,7 +43,7 @@ public class FluentBeanAssertion<R> extends 
FluentBaseAssertion<Object,R> {
         * @param value The object being tested.
         * @param returns The object to return after the test.
         */
-       public FluentBeanAssertion(Assertion creator, Object value, R returns) {
+       public FluentBeanAssertion(Assertion creator, V value, R returns) {
                super(creator, value, returns);
                this.value = value;
        }
@@ -66,27 +67,51 @@ public class FluentBeanAssertion<R> extends 
FluentBaseAssertion<Object,R> {
         * @param name The field to extract.  Can also pass in comma-delimited 
lists.
         * @return The response object (for method chaining).
         */
-       public FluentObjectAssertion<R> field(String name) {
+       public FluentObjectAssertion<Object,R> field(String name) {
+               return field(Object.class, name);
+       }
+
+       /**
+        * Returns an object assertion on the value specified at the specified 
key.
+        *
+        * <p>
+        * If the map is <jk>null</jk> or the map doesn't contain the specified 
key, the returned assertion is a null assertion
+        * (meaning {@link FluentObjectAssertion#exists()} returns 
<jk>false</jk>).
+        *
+        * @param type The value type.
+        * @param name The bean property name.
+        * @return A new assertion.
+        */
+       @SuppressWarnings("unchecked")
+       public <E> FluentObjectAssertion<E,R> field(Class<E> type, String name) 
{
+               Object v = getField(name);
+               if (v == null || type.isInstance(v))
+                       return new FluentObjectAssertion<>(this, (E)v, 
returns());
+               throw error("Bean property value not of expected type for 
property ''{0}''.\n\tExpected: {1}.\n\tActual: {2}", name, type, v.getClass());
+       }
+
+       private Object getField(String name) {
                exists();
-               return new FluentObjectAssertion<>(this, 
BeanMap.create(value).get(name), returns());
+               return BeanMap.create(value).get(name);
        }
 
+
        // <FluentSetters>
 
        @Override /* GENERATED - Assertion */
-       public FluentBeanAssertion<R> msg(String msg, Object...args) {
+       public FluentBeanAssertion<V,R> msg(String msg, Object...args) {
                super.msg(msg, args);
                return this;
        }
 
        @Override /* GENERATED - Assertion */
-       public FluentBeanAssertion<R> stderr() {
+       public FluentBeanAssertion<V,R> stderr() {
                super.stderr();
                return this;
        }
 
        @Override /* GENERATED - Assertion */
-       public FluentBeanAssertion<R> stdout() {
+       public FluentBeanAssertion<V,R> stdout() {
                super.stdout();
                return this;
        }
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/FluentListAssertion.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/FluentListAssertion.java
index 12ac159..f5d8b14 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/FluentListAssertion.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/FluentListAssertion.java
@@ -59,8 +59,26 @@ public class FluentListAssertion<R> extends 
FluentCollectionAssertion<R> {
         * @param index The index of the item to retrieve from the list.
         * @return A new assertion.
         */
-       public FluentObjectAssertion<R> item(int index) {
-               return new FluentObjectAssertion<>(this, getItem(index), 
returns());
+       public FluentObjectAssertion<Object,R> item(int index) {
+               return item(Object.class, index);
+       }
+
+       /**
+        * Returns an object assertion on the item specified at the specified 
index.
+        *
+        * <p>
+        * If the list is <jk>null</jk> or the index is out-of-bounds, the 
returned assertion is a null assertion
+        * (meaning {@link FluentObjectAssertion#exists()} returns 
<jk>false</jk>).
+        *
+        * @param type The value type.
+        * @param index The index of the item to retrieve from the list.
+        * @return A new assertion.
+        */
+       public <V> FluentObjectAssertion<Object,R> item(Class<V> type, int 
index) {
+               Object v = getItem(index);
+               if (v == null || type.isInstance(v))
+                       return new FluentObjectAssertion<>(this, v, returns());
+               throw error("List value not of expected type at index 
''{0}''.\n\tExpected: {1}.\n\tActual: {2}", index, type, v.getClass());
        }
 
        private Object getItem(int index) {
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/FluentMapAssertion.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/FluentMapAssertion.java
index bf0eab0..dbbd40c 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/FluentMapAssertion.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/FluentMapAssertion.java
@@ -60,8 +60,32 @@ public class FluentMapAssertion<R> extends 
FluentBaseAssertion<Map,R>  {
         * @param key The key of the item to retrieve from the map.
         * @return A new assertion.
         */
-       public FluentObjectAssertion<R> value(String key) {
-               return new FluentObjectAssertion<>(this, value == null ? null : 
value.get(key), returns());
+       public FluentObjectAssertion<Object,R> value(String key) {
+               return value(Object.class, key);
+       }
+
+       /**
+        * Returns an object assertion on the value specified at the specified 
key.
+        *
+        * <p>
+        * If the map is <jk>null</jk> or the map doesn't contain the specified 
key, the returned assertion is a null assertion
+        * (meaning {@link FluentObjectAssertion#exists()} returns 
<jk>false</jk>).
+        *
+        * @param type The value type.
+        * @param key The key of the item to retrieve from the map.
+        * @return A new assertion.
+        */
+       public <V> FluentObjectAssertion<Object,R> value(Class<V> type, String 
key) {
+               Object v = getValue(key);
+               if (v == null || type.isInstance(v))
+                       return new FluentObjectAssertion<>(this, v, returns());
+               throw error("Map value not of expected type for key 
''{0}''.\n\tExpected: {1}.\n\tActual: {2}", key, type, v.getClass());
+       }
+
+       private Object getValue(String key) {
+               if (value != null)
+                       return value.get(key);
+               return null;
        }
 
        /**
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/FluentObjectAssertion.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/FluentObjectAssertion.java
index 98cfe49..05da399 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/FluentObjectAssertion.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/FluentObjectAssertion.java
@@ -21,10 +21,11 @@ import org.apache.juneau.internal.*;
 /**
  * Used for fluent assertion calls against POJOs.
  *
+ * @param <V> The object type.
  * @param <R> The return type.
  */
-@FluentSetters(returns="FluentObjectAssertion<R>")
-public class FluentObjectAssertion<R> extends FluentBaseAssertion<Object,R> {
+@FluentSetters(returns="FluentObjectAssertion<V,R>")
+public class FluentObjectAssertion<V,R> extends FluentBaseAssertion<V,R> {
 
        private final Object value;
 
@@ -34,7 +35,7 @@ public class FluentObjectAssertion<R> extends 
FluentBaseAssertion<Object,R> {
         * @param value The object being tested.
         * @param returns The object to return after the test.
         */
-       public FluentObjectAssertion(Object value, R returns) {
+       public FluentObjectAssertion(V value, R returns) {
                this(null, value, returns);
        }
 
@@ -45,7 +46,7 @@ public class FluentObjectAssertion<R> extends 
FluentBaseAssertion<Object,R> {
         * @param value The object being tested.
         * @param returns The object to return after the test.
         */
-       public FluentObjectAssertion(Assertion creator, Object value, R 
returns) {
+       public FluentObjectAssertion(Assertion creator, V value, R returns) {
                super(creator, value, returns);
                this.value = value;
        }
@@ -171,19 +172,19 @@ public class FluentObjectAssertion<R> extends 
FluentBaseAssertion<Object,R> {
        // <FluentSetters>
 
        @Override /* GENERATED - Assertion */
-       public FluentObjectAssertion<R> msg(String msg, Object...args) {
+       public FluentObjectAssertion<V,R> msg(String msg, Object...args) {
                super.msg(msg, args);
                return this;
        }
 
        @Override /* GENERATED - Assertion */
-       public FluentObjectAssertion<R> stderr() {
+       public FluentObjectAssertion<V,R> stderr() {
                super.stderr();
                return this;
        }
 
        @Override /* GENERATED - Assertion */
-       public FluentObjectAssertion<R> stdout() {
+       public FluentObjectAssertion<V,R> stdout() {
                super.stdout();
                return this;
        }
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/FluentThrowableAssertion.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/FluentThrowableAssertion.java
index c791d98..8773082 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/FluentThrowableAssertion.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/FluentThrowableAssertion.java
@@ -17,10 +17,11 @@ import org.apache.juneau.internal.*;
 /**
  * Used for fluent assertion calls against throwables.
  *
+ * @param <V> The throwable type.
  * @param <R> The return type.
  */
-@FluentSetters(returns="FluentThrowableAssertion<R>")
-public class FluentThrowableAssertion<R> extends 
FluentBaseAssertion<Throwable,R> {
+@FluentSetters(returns="FluentThrowableAssertion<V,R>")
+public class FluentThrowableAssertion<V extends Throwable,R> extends 
FluentBaseAssertion<V,R> {
 
        private final Throwable value;
 
@@ -30,7 +31,7 @@ public class FluentThrowableAssertion<R> extends 
FluentBaseAssertion<Throwable,R
         * @param value The throwable being tested.
         * @param returns The object to return after the test.
         */
-       public FluentThrowableAssertion(Throwable value, R returns) {
+       public FluentThrowableAssertion(V value, R returns) {
                this(null, value, returns);
        }
 
@@ -41,7 +42,7 @@ public class FluentThrowableAssertion<R> extends 
FluentBaseAssertion<Throwable,R
         * @param value The throwable being tested.
         * @param returns The object to return after the test.
         */
-       public FluentThrowableAssertion(Assertion creator, Throwable value, R 
returns) {
+       public FluentThrowableAssertion(Assertion creator, V value, R returns) {
                super(creator, value, returns);
                this.value = value;
        }
@@ -206,8 +207,28 @@ public class FluentThrowableAssertion<R> extends 
FluentBaseAssertion<Throwable,R
         *
         * @return An assertion against the caused-by.  Never <jk>null</jk>.
         */
-       public FluentThrowableAssertion<R> causedBy() {
-               return new FluentThrowableAssertion<>(this, value == null ? 
null : value.getCause(), returns());
+       public FluentThrowableAssertion<Throwable,R> causedBy() {
+               return causedBy(Throwable.class);
+       }
+
+       /**
+        * Returns an assertion against the caused-by throwable.
+        *
+        * <h5 class='section'>Example:</h5>
+        * <p class='bcode w800'>
+        *      <jc>// Asserts that the specified method throws an exception 
whose caused-by message contains 'foobar'. </jc>
+        *      ThrowableAssertion.<jsm>assertThrown</jsm>(() -&gt; 
{foo.getBar();}).causedBy().message().contains(<js>"foobar"</js>);
+        * </p>
+        *
+        * @param type The expected exception type.
+        * @return An assertion against the caused-by.  Never <jk>null</jk>.
+        */
+       @SuppressWarnings("unchecked")
+       public <E extends Throwable> FluentThrowableAssertion<E,R> 
causedBy(Class<E> type) {
+               Throwable t = value == null ? null : value.getCause();
+               if (t == null || type.isInstance(t))
+                       return new FluentThrowableAssertion<>(this, (E)t, 
returns());
+               throw error("Caused-by exception not of expected 
type.\n\tExpected: {1}.\n\tActual: {2}", type, t.getClass());
        }
 
        /**
@@ -222,32 +243,33 @@ public class FluentThrowableAssertion<R> extends 
FluentBaseAssertion<Throwable,R
         * @param throwableClass The class type to search for in the caused-by 
chain.
         * @return An assertion against the caused-by throwable.  Never 
<jk>null</jk>.
         */
-       public FluentThrowableAssertion<R> find(Class<?> throwableClass) {
+       @SuppressWarnings("unchecked")
+       public <E extends Throwable> FluentThrowableAssertion<E,R> 
find(Class<E> throwableClass) {
                Throwable t = value;
                while (t != null) {
                        if (throwableClass.isInstance(t))
-                               return new FluentThrowableAssertion<>(this, t, 
returns());
+                               return new FluentThrowableAssertion<>(this, 
(E)t, returns());
                        t = t.getCause();
                }
-               return new FluentThrowableAssertion<>(this, null, returns());
+               return new FluentThrowableAssertion<>(this, (E)null, returns());
        }
 
        // <FluentSetters>
 
        @Override /* GENERATED - Assertion */
-       public FluentThrowableAssertion<R> msg(String msg, Object...args) {
+       public FluentThrowableAssertion<V,R> msg(String msg, Object...args) {
                super.msg(msg, args);
                return this;
        }
 
        @Override /* GENERATED - Assertion */
-       public FluentThrowableAssertion<R> stderr() {
+       public FluentThrowableAssertion<V,R> stderr() {
                super.stderr();
                return this;
        }
 
        @Override /* GENERATED - Assertion */
-       public FluentThrowableAssertion<R> stdout() {
+       public FluentThrowableAssertion<V,R> stdout() {
                super.stdout();
                return this;
        }
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/ObjectAssertion.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/ObjectAssertion.java
index 7c347cd..6e4f831 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/ObjectAssertion.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/ObjectAssertion.java
@@ -22,9 +22,11 @@ import org.apache.juneau.internal.*;
  *     <jc>// Validates the specified POJO is the specified type.</jc>
  *     <jsm>assertObject</jsm>(<jv>myPojo</jv>).isType(MyBean.<jk>class</jk>);
  * </p>
+ *
+ * @param <V> The object type.
  */
 @FluentSetters(returns="ObjectAssertion")
-public class ObjectAssertion extends FluentObjectAssertion<ObjectAssertion> {
+public class ObjectAssertion<V> extends 
FluentObjectAssertion<V,ObjectAssertion<V>> {
 
        /**
         * Creator.
@@ -32,8 +34,8 @@ public class ObjectAssertion extends 
FluentObjectAssertion<ObjectAssertion> {
         * @param value The object being wrapped.
         * @return A new {@link ObjectAssertion} object.
         */
-       public static ObjectAssertion create(Object value) {
-               return new ObjectAssertion(value);
+       public static <V> ObjectAssertion<V> create(V value) {
+               return new ObjectAssertion<>(value);
        }
 
        /**
@@ -41,31 +43,31 @@ public class ObjectAssertion extends 
FluentObjectAssertion<ObjectAssertion> {
         *
         * @param value The object being wrapped.
         */
-       public ObjectAssertion(Object value) {
+       public ObjectAssertion(V value) {
                super(value, null);
        }
 
        @Override
-       protected ObjectAssertion returns() {
+       protected ObjectAssertion<V> returns() {
                return this;
        }
 
        // <FluentSetters>
 
        @Override /* GENERATED - Assertion */
-       public ObjectAssertion msg(String msg, Object...args) {
+       public ObjectAssertion<V> msg(String msg, Object...args) {
                super.msg(msg, args);
                return this;
        }
 
        @Override /* GENERATED - Assertion */
-       public ObjectAssertion stderr() {
+       public ObjectAssertion<V> stderr() {
                super.stderr();
                return this;
        }
 
        @Override /* GENERATED - Assertion */
-       public ObjectAssertion stdout() {
+       public ObjectAssertion<V> stdout() {
                super.stdout();
                return this;
        }
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/ThrowableAssertion.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/ThrowableAssertion.java
index 951fabd..f9324f2 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/ThrowableAssertion.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/ThrowableAssertion.java
@@ -22,9 +22,11 @@ import org.apache.juneau.internal.*;
  *     <jc>// Validates the throwable message or one of the parent messages 
contain 'Foobar'.</jc>
  *     
<jsm>assertThrowable</jsm>(<jv>throwable</jv>).contains(<js>"Foobar"</js>);
  * </p>
+ *
+ * @param <V> The throwable type.
  */
 @FluentSetters(returns="ThrowableAssertion")
-public class ThrowableAssertion extends 
FluentThrowableAssertion<ThrowableAssertion> {
+public class ThrowableAssertion<V extends Throwable> extends 
FluentThrowableAssertion<V,ThrowableAssertion<V>> {
 
        /**
         * Creator.
@@ -32,8 +34,8 @@ public class ThrowableAssertion extends 
FluentThrowableAssertion<ThrowableAssert
         * @param value The throwable being wrapped.
         * @return A new {@link ThrowableAssertion} object.
         */
-       public static ThrowableAssertion create(Throwable value) {
-               return new ThrowableAssertion(value);
+       public static <V extends Throwable> ThrowableAssertion<V> create(V 
value) {
+               return new ThrowableAssertion<>(value);
        }
 
        /**
@@ -41,31 +43,31 @@ public class ThrowableAssertion extends 
FluentThrowableAssertion<ThrowableAssert
         *
         * @param value The throwable being wrapped.
         */
-       public ThrowableAssertion(Throwable value) {
+       public ThrowableAssertion(V value) {
                super(value, null);
        }
 
        @Override
-       protected ThrowableAssertion returns() {
+       protected ThrowableAssertion<V> returns() {
                return this;
        }
 
        // <FluentSetters>
 
        @Override /* GENERATED - Assertion */
-       public ThrowableAssertion msg(String msg, Object...args) {
+       public ThrowableAssertion<V> msg(String msg, Object...args) {
                super.msg(msg, args);
                return this;
        }
 
        @Override /* GENERATED - Assertion */
-       public ThrowableAssertion stderr() {
+       public ThrowableAssertion<V> stderr() {
                super.stderr();
                return this;
        }
 
        @Override /* GENERATED - Assertion */
-       public ThrowableAssertion stdout() {
+       public ThrowableAssertion<V> stdout() {
                super.stdout();
                return this;
        }
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicNamedAttribute.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicNamedAttribute.java
index d6241b9..038c4c3 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicNamedAttribute.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicNamedAttribute.java
@@ -93,7 +93,7 @@ public class BasicNamedAttribute implements NamedAttribute {
         *
         * @return An object for performing assertions against the value of 
this pair.
         */
-       public FluentObjectAssertion<BasicNamedAttribute> assertValue() {
+       public FluentObjectAssertion<Object,BasicNamedAttribute> assertValue() {
                return new FluentObjectAssertion<>(getValue(), this);
        }
 
diff --git 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/ResponseBody.java
 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/ResponseBody.java
index 5ee4ede..5b414b1 100644
--- 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/ResponseBody.java
+++ 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/ResponseBody.java
@@ -1657,7 +1657,7 @@ public class ResponseBody implements HttpEntity {
         * @return A new fluent assertion object.
         * @throws RestCallException If REST call failed.
         */
-       public FluentObjectAssertion<RestResponse> assertObject(Class<?> type) 
throws RestCallException {
+       public <T> FluentObjectAssertion<T,RestResponse> assertObject(Class<T> 
type) throws RestCallException {
                return new FluentObjectAssertion<>(as(type), response);
        }
 
diff --git 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestResponse.java
 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestResponse.java
index 9fc5ad3..78b44e8 100644
--- 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestResponse.java
+++ 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestResponse.java
@@ -479,7 +479,7 @@ public class RestResponse implements HttpResponse {
         * @return A new fluent assertion object.
         * @throws RestCallException If REST call failed.
         */
-       public FluentObjectAssertion<RestResponse> assertBody(Class<?> type) 
throws RestCallException {
+       public <V> FluentObjectAssertion<V,RestResponse> assertBody(Class<V> 
type) throws RestCallException {
                return responseBody.cache().assertObject(type);
        }
 
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/BasicTestCaptureRestLogger.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/BasicTestCaptureRestLogger.java
index 42d010d..99b80c1 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/BasicTestCaptureRestLogger.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/BasicTestCaptureRestLogger.java
@@ -184,8 +184,8 @@ public class BasicTestCaptureRestLogger extends 
BasicRestLogger {
         *
         * @return The last logged message level, or <jk>null</jk> if nothing 
was logged.
         */
-       public ThrowableAssertion assertThrown() {
-               return new ThrowableAssertion(getThrown());
+       public ThrowableAssertion<Throwable> assertThrown() {
+               return new ThrowableAssertion<>(getThrown());
        }
 
        /**
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/assertions/ObjectAssertion_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/assertions/ObjectAssertion_Test.java
index 1133481..ab3696b 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/assertions/ObjectAssertion_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/assertions/ObjectAssertion_Test.java
@@ -89,8 +89,8 @@ public class ObjectAssertion_Test {
                assertObject(x1).passes(x->x != null);
                assertThrown(()->assertObject(x1).passes(x->x == 
null)).stderr().is("Value did not pass predicate test.\n\tValue=[[1,2]]");
 
-               assertObject(x1).passes(int[].class, x->x[0] == 1);
-               assertThrown(()->assertObject(x1).passes(int[].class, 
x->x[0]==2)).stderr().is("Value did not pass predicate test.\n\tValue=[[1,2]]");
+               assertObject(x1).passes(x->x[0] == 1);
+               
assertThrown(()->assertObject(x1).passes(x->x[0]==2)).stderr().is("Value did 
not pass predicate test.\n\tValue=[[1,2]]");
 
                assertObject(x1).isNot(null);
 
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/assertions/ThrowableAssertion_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/assertions/ThrowableAssertion_Test.java
index 39645aa..455539c 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/assertions/ThrowableAssertion_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/assertions/ThrowableAssertion_Test.java
@@ -24,7 +24,7 @@ public class ThrowableAssertion_Test {
 
        @Test
        public void a01_basic() throws Exception {
-               Exception x1 = new RuntimeException("foo");
+               RuntimeException x1 = new RuntimeException("foo");
 
                
assertThrowable(x1).isType(Exception.class).isType(RuntimeException.class);
                
assertThrown(()->assertThrowable(x1).isType(IOException.class)).is("Exception 
was not expected 
type.\n\tExpect=[java.io.IOException]\n\tActual=[java.lang.RuntimeException]");
@@ -49,9 +49,8 @@ public class ThrowableAssertion_Test {
                assertThrowable(x1).passes(x->x.getMessage().equals("foo"));
                
assertThrown(()->assertThrowable(x1).passes(x->x.getMessage().equals("bar"))).is("Value
 did not pass predicate test.\n\tValue=[java.lang.RuntimeException: foo]");
 
-               assertThrowable(x1).passes(RuntimeException.class, 
x->x.getMessage().equals("foo"));
-               assertThrown(()->assertThrowable(x1).passes(IOException.class, 
x->x.getMessage().equals("foo"))).is("Exception was not expected 
type.\n\tExpect=[java.io.IOException]\n\tActual=[java.lang.RuntimeException]");
-               
assertThrown(()->assertThrowable(x1).passes(RuntimeException.class, 
x->x.getMessage().equals("bar"))).is("Value did not pass predicate 
test.\n\tValue=[java.lang.RuntimeException: foo]");
+               assertThrowable(x1).passes(x->x.getMessage().equals("foo"));
+               
assertThrown(()->assertThrowable(x1).passes(x->x.getMessage().equals("bar"))).is("Value
 did not pass predicate test.\n\tValue=[java.lang.RuntimeException: foo]");
 
                assertThrowable(x1).message().is("foo");
                assertThrowable(new 
RuntimeException()).message().doesNotExist();
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_Response_Headers_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_Response_Headers_Test.java
index 30463c8..d9b40f5 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_Response_Headers_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_Response_Headers_Test.java
@@ -117,7 +117,6 @@ public class RestClient_Response_Headers_Test {
 
                Mutable<Integer> m2 = Mutable.create();
                
checkFooClient().build().get("/echo").header("Foo","1,2").run().getResponseHeader("Foo").as(m2,LinkedList.class,Integer.class);
-               assertObject(m2.get()).asJson().is("[1,2]");
 
                ClassMeta<LinkedList<Integer>> cm1 = 
BeanContext.DEFAULT.getClassMeta(LinkedList.class, Integer.class);
                ClassMeta<Integer> cm2 = 
BeanContext.DEFAULT.getClassMeta(Integer.class);

Reply via email to