org.mutabilitydetector.unittesting.MutabilityAssert Maven / Gradle / Ivy
Show all versions of MutabilityDetector Show documentation
package org.mutabilitydetector.unittesting;
/*
* #%L
* MutabilityDetector
* %%
* Copyright (C) 2008 - 2014 Graham Allan
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import static org.mutabilitydetector.Configurations.OUT_OF_THE_BOX_CONFIGURATION;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import org.hamcrest.Matcher;
import org.mutabilitydetector.AnalysisResult;
import org.mutabilitydetector.Configuration;
import org.mutabilitydetector.ConfigurationBuilder;
import org.mutabilitydetector.Configurations;
import org.mutabilitydetector.IsImmutable;
import org.mutabilitydetector.MutabilityReason;
import org.mutabilitydetector.MutableReasonDetail;
/**
*
* Mutability Detector
*
* Mutability Detector allows you to write a unit test that checks your
* classes are immutable.
*
* Help Guide
* Contents
*
* - Preamble
*
*
* - Your first test case.
* - A more specific assertion
* - Allowing a reason for mutability
*
*
* - Hardcoding analysis results
*
*
*
*
*
*
*
* About this help guide
*
* The help contents here are also available on the project's JavaDoc.
*
* This style of documentation is used as it provides content suitable for a web
* page and for offline use in the JavaDoc viewer of your favourite IDE. It has
* been shamelessly stolen from inspired by the Mockito
* project, thanks guys.
*
* About these examples
I am assuming JUnit as the
* unit testing library. However, Mutability Detector should work with any unit
* testing library that uses the exception mechanism for their assertions, such
* as TestNG. If Mutability Detector is incompatible with your favourite testing
* library, please get in touch, and we'll see what we can do about that.
*
* Your first test case.
*
* The most simple assertion you can make will look something like this:
*
*
*
* import static org.mutabilitydetector.unittesting.MutabilityAssert.assertImmutable;
*
* @Test public void checkMyClassIsImmutable() {
* assertImmutable(MyClass.class);
* }
*
*
*
*
* This assertion will trigger an analysis of MyClass
, passing if
* found to be immutable, failing if found to be mutable.
*
*
*
* Configuring the assertion
*
* The method used above is a shortcut for more expressive forms of the
* assertion, and does not allow any further configuration. An equivalent
* assertion is:
*
*
*
*
* import static org.mutabilitydetector.unittesting.MutabilityAssert.assertInstancesOf;
* import static org.mutabilitydetector.unittesting.MutabilityMatchers.areImmutable;
*
* @Test public void checkMyClassIsImmutable() {
* assertInstancesOf(MyClass.class, areImmutable());
* }
*
*
*
* This is the form that can be used for extra configuration of the assertion.
* Let's take a look at an assertion that is configured differently. Consider a
* class which is immutable, except for fields not being declared
* final
. According to Java Concurrency
* In Practice, instances of classes like this, as long as they are
* safely published are still considered effectively immutable.
* Please note however, Mutability Detector does not check that objects are
* safely published.
* To represent this in a unit test, the assertion would like this:
*
*
*
* import static org.mutabilitydetector.unittesting.MutabilityAssert.assertInstancesOf;
* import static org.mutabilitydetector.unittesting.MutabilityMatchers.areEffectivelyImmutable;
* import static org.mutabilitydetector.unittesting.AllowedReason.allowingNonFinalFields;
*
* @Test public void checkMyClassIsImmutable() {
* assertInstancesOf(MyClassWhereTheFieldsAreNotFinal.class,
* areEffectivelyImmutable(),
* allowingNonFinalFields());
* }
*
*
* See also:
*
* - {@link IsImmutable#EFFECTIVELY_IMMUTABLE}
*
*
*
* The second parameter to the method
* {@link MutabilityAssert#assertInstancesOf(Class, Matcher)} is a
* Matcher<AnalysisResult>
, where Matcher
is a
* hamcrest matcher, and
* {@link AnalysisResult} is provided by Mutability Detector to represent the
* result of the static analysis performed on the given class. This means, if
* none of the out-of-the-box matchers are quite right for your scenario, you
* can supply your own. Your implementation of {@link Matcher#matches(Object)}
* should return true for a test pass, false for a test failure.
*
*
*
* Allowing a reason
* There can also be cases where your class is found to be mutable, but you know
* for your scenario that it's an acceptable reason. Consider the following
* class:
*
*
* public abstract class AbstractIntHolder {
* private final int intField;
*
* public AbstractIntHolder(int intToStore) {
* this.intField = intToStore;
* }
* }
*
*
*
* In this case, if you assert AbstractIntHolder
is immutable, the
* test will fail. This is because AbstractIntHolder can be subclassed, which
* means clients of this class, who for example, accept parameters of this type
* and store them to fields, cannot depend on receiving a concrete, immutable
* object. If, in your code, you know that all subclasses will also be immutable
* (hopefully you have tests for them too) then you can say that it is okay that
* this class can be subclassed, because you know all subclasses are immutable
* as well.
*
*
* Given such a scenario, the way to get your test to pass, and still provide a
* check that the class doesn't become mutable by some other cause, is to
* allow a reason for mutability. An example of allowing said reason for
* AbstractIntHolder
could look like this:
*
*
*
*
* import static org.mutabilitydetector.unittesting.MutabilityAssert.assertInstancesOf;
* import static org.mutabilitydetector.unittesting.MutabilityMatchers.areEffectivelyImmutable;
* import static org.mutabilitydetector.unittesting.AllowedReason.allowingForSubclassing;
*
* @Test public void checkMyClassIsImmutable() {
* assertInstancesOf(AbstractIntHolder.class, areImmutable(), allowingForSubclassing());
* }
*
*
*
* This will allow your test to pass, but fail for any other reasons that are
* introduced, e.g. if someone adds a setter method.
*
*
* Similar to the Matcher<AnalysisResult>
parameter, the
* allowed reason parameter of
* {@link #assertInstancesOf(Class, Matcher, Matcher)} is a
* Matcher<{@link MutableReasonDetail}>
. Mutability Detector
* will provide only a few out-of-the-box implementations for this, which are
* unlikely to cover each scenario where you want to permit a certain aspect of
* mutability.
*
* Out-of-the-box allowed reasons
*
*
Abstract class with immutable
* implementation
* It can be useful to write an abstract class, designed for extension, which is
* immutable. To ensure that a concrete class B, extending abstract class A is
* immutable, it is necessary to test that both A
and
* B
are immutable. However, if you write the assertion
* assertImmutable(A.class);
, it will fail, as it can be subclassed
* (see {@link MutabilityReason#CAN_BE_SUBCLASSED}). To specifically allow this,
* use the allowed reason: {@link AllowedReason#allowingForSubclassing()}
*
* For example:
* assertInstancesOf(A.class, areImmutable(), allowingForSubclassing());
*
* Depending on other classes being
* immutable
* Consider the following code:
*
* public final class MyImmutable {
* public final ShouldAlsoBeImmutable field;
*
* public MyImmutable(ShouldAlsoBeImmutable dependsOnThisBeingImmutable) {
* this.field = dependsOnThisBeingImmutable;
* }
* }
*
*
*
* If ShouldAlsoBeImmutable
is not a concrete class (an
* interface
or abstract
class),
* assertImmutable(MyImmutable.class);
will fail, as there's no
* guarantee that the runtime implementation of ShouldBeImmutable
* is actually immutable. A common example is taking a parameter of
* java.util.List
, where you require that it is an immutable
* implementation, e.g: a copy created with
* {@link Collections#unmodifiableList(List)}. For this scenario, use
* {@link AllowedReason#provided(Class)}.
*
* To make the above example pass, use an allowed reason like so:
*
*
*
*
* assertInstancesOf(MyImmutable.class,
* areImmutable(),
* AllowedReason.provided(ShouldAlsoBeImmutable.class).isAlsoImmutable());
*
*
*
*
*
* In some cases, classes use a generic type, and treat that type as immutable.
* Since the runtime type of a generic class cannot be known by the class
* at compile time, MutabilityDetector cannot say for sure that the type will
* be immutable and raises it as an error.
*
* Consider the following class:
*
*
*
* public final HasGenericField {
* public final T genericThing;
*
* public HasGenericField(T genericThing) {
* this.genericThing = genericThing;
* }
* }
*
*
* In this case <T> may or may not be an immutable type at runtime,
* it depends on what generic type is used to construct the instance. To prevent
* classes like this being declared as immutable, use an assertion like this:
*
*
*
* assertInstancesOf(HasGenericField.class,
* areImmutable(),
* AllowedReason.provided("T").isAlsoImmutable());
*
*
*
* Mutability Detector does not currently behave any differently for bounded type
* parameters such as T extends Foo
or T super Foo & Bar
.
* Only the name of the generic type is considered, and must match exactly the
* name of the type parameter used by the class.
*
*
*
* Non-final fields If you have fields
* which are neither mutated nor reassigned, you can suppress warnings about
* them not being declared as final. Since the non-final field warning relates
* to visibility in the Java Memory Model, and there are other ways to guarantee
* visibility (e.g. assigning before a volatile write) it may be desirable.
* Consider the following class:
*
*
*
* public final class NonFinalField {
* private String myField;
*
* public NonFinalField(String myField) {
* this.myField = myField;
* }
*
* public String getMyField() {
* return myField;
* }
* }
*
*
*
* This can be made to pass by allowing non-final fields, like so:
*
*
*
* assertInstancesOf(NonFinalField.class,
* areImmutable(),
* AllowedReason.allowingNonFinalFields());
*
*
*
* Safely copying into collection
* field
* Fields of collection types are normally interfaces (e.g. List, Set,
* Iterable), and assigning these types to a field will result in a warning.
* Mutability Detector has support for recognising the pattern of copying and
* wrapping in an unmodifiable collection, however, it is limited to types and
* methods from the standard JDK. Consider the following class:
*
*
*
* import java.util.List;
*
* public final class HasCollectionField {
* private final List<String> myStrings;
*
* public HasCollectionField(List<String> strings) {
* List<String> copy = copyIntoNewList(strings);
* List<String> unmodifiable = wrapWithUnmodifiable(strings);
* this.myStrings = unmodifiable;
* }
* }
*
*
*
* In this case we safely copy the list (copyIntoNewList
) and the
* copy is then wrapped in an unmodifiable list that will prevent mutation (
* wrapWithUnmodifiable
). However, since Mutability Detector is
* unaware of these two methods, it will conclude that a mutable
* List
type has been assigned to the private field.
*
* This can be made to pass with the following:
*
*
*
* assertInstancesOf(HasCollectionField.class,
* areImmutable(),
* AllowedReason.assumingFields("myStrings").areSafelyCopiedUnmodifiableCollectionsWithImmutableElements());
*
*
*
* This also assumes that the collection contains only immutable elements, and
* will suppress warnings generated when, for example, the field is a
* {@link List} of mutable {@link Date}s.
*
* Mutable field never modified
* While it is absolutely possible to build an immutable object with mutable
* fields, Mutability Detector errs on the side of caution. Thus, your class
* could have a field of a mutable type, which neither escapes, nor is mutated
* by the owning class, but still fails a test for immutability.
*
* Consider the following class:
*
*
*
* import java.util.Date;
*
* public final class HasDateField {
* private final Date myDate;
*
* public HasDateField(Date date) {
* this.myDate = new Date(date.getTime());
* }
*
* public Date getDate() {
* return new Date(myDate.getTime());
* }
* }
*
*
*
*
* A test for this class fails because the field myDate
is a
* mutable type. This can be made to pass with the following:
*
*
*
* assertInstancesOf(HasDateField.class,
* areImmutable(),
* AllowedReason.assumingFields("myDate").areNotModifiedAndDoNotEscape());
*
*
*
* Caching values internally
* As with {@link String}, it is possible to reassign fields or mutate internal
* state and still be immutable. As long as callers cannot observe the change
* the class can be deemed immutable.
*
* Consider the following class:
*
*
*
* public final class MutatesAsInternalCaching {
* private final String myString;
* private final String otherString;
* private int lengthWhenConcatenated;
* public MutatesAsInternalCaching(String myString, String otherString) {
* this.myString = myString;
* this.otherString = otherString;
* }
*
* public int getConcatenatedLength() {
* if (lengthWhenConcatenated == 0) {
* lengthWhenConcatenated = myString.concat(otherString).length();
* }
* return lengthWhenConcatenated;
* }
* }
*
*
*
* Here, the field lengthWhenConcatenated
is computed lazily. While
* there is a field reassignment, which is a mutation, callers will never
* perceive the mutation, as the calculation is done on the first request. Even
* in a multithreaded environment, this is safe, and will result in no
* observable mutation. Since the result is computed from other immutable
* values, if multiple threads hit the race condition of seeing an empty value
* while another thread is computing the result, the field will always be set to
* the same value. Multiple assignments will appear as exactly one assignment,
* just as with a final field.
*
* This is called a 'benign data race', and exists in {@link String}, with its
* {@link #hashCode()} method.
*
* WARNING: This technique should be used with care, as it is very easy to get
* wrong.
*
* To allow this in tests, use an assertion like the following:
*
*
*
* assertInstancesOf(MutatesAsInternalCaching.class,
* areImmutable(),
* AllowedReason.assumingFields("lengthWhenConcatenated").areModifiedAsPartOfAnUnobservableCachingStrategy());
*
*
*
* This will also allow the use of mutable types and collections, not just
* reassignments of primitive fields. Thus populating an array or collection for
* future caching should also be allowed with this matcher.
*
* Writing your own allowed reasons
*
* If none of the out-of-the-box allowed reasons suit your needs, it is possible
* to supply your own implementation. The allowed reason in the signature of
* {@link MutabilityAssert#assertInstancesOf(Class, Matcher, Matcher)} is a
* Hamcrest Matcher<{@link MutableReasonDetail}>
. For a
* mutable class to pass the test, each {@link MutableReasonDetail} of the
* {@link AnalysisResult} (provided by Mutability Detector) must be matched by
* at least one allowed reason.
*
*
*
* Configuring MutabilityAssert to use Hardcoded
* Results
*
* As of version 0.9, Mutability Detector uses a predefined list of hardcoded
* results, in order to improve the accuracy of the analysis. For example, prior
* to 0.9, java.lang.String was considered to be mutable. The out of the box hardcoded results includes
* a non-exhaustive list of immutable classes from the standard JDK.
*
* See also:
*
* - {@link Configurations#JDK_CONFIGURATION}
*
*
*
*
* If you have found that Mutability Detector is unable to correctly analyse one
* of your classes, or a class in a library you use, you may wish to add your
* class to the list of predefined results. Follow these steps to choose your
* own predefined list.
*
*
Why Would You Want To Hardcode Results?
*
* Imagine a couple of classes like this:
*
*
*
*
* @Immutable
* public final class ActuallyImmutable {
* // is immutable, but like java.lang.String, is incorrectly
* // called mutable.
* }
*
* @Immutable
* public final class UsesActuallyImmutable {
* public final ActuallyImmutable myImmutableField = ...;
* }
*
* // in a test case
* MutabilityAssert.assertImmutable(UsesActuallyImmutable.class); // this test fails
*
*
*
* Because there's an error in the analysis of ActuallyImmutable
,
* this "taints" UsesActuallyImmutable
, which will also be
* considered mutable. Because of the transitive nature of a false positive,
* this can cause Mutability Detector to think that entire object graphs are
* mutable when they're not. Hardcoding your own results is a way to overcome
* incorrect analysis.
*
* Using A Different Asserter
*
* To be able to hardcode results, you need your own instance of
* {@link MutabilityAsserter}. Normally assertions are made using the class
* {@link MutabilityAssert}. To choose different options from this class, you
* must create and make available your own asserter with its own configuration.
* Do this by constructing an instance of MutabilityAssert, like so:
*
*
*
* public class SomeClassAccessibleByMyTests {
* public static final MutabilityAsserter MUTABILITY = MutabilityAsserter.configured(...);
* }
*
*
* This allows your test case to have an assertion like:
*
*
* // in a test case
* MUTABILITY.assertImmutable(MyClass.class);
*
*
*
*
* Hardcoding Analysis Results
*
* Notice in the above example, the parameters given to the
* MutabilityAssert.configured()
method are not shown. The
* parameter, of type {@link Configuration}, is what will contain your hardcoded
* results. In the following example, To overcome this, instantiate
* MutabilityAsserter like this:
*
*
*
* // as a field
* MutabilityAsserter MUTABILITY = MutabilityAsserter.configured(new ConfigurationBuilder() {
* @Override public void configure() {
* hardcodeAsDefinitelyImmutable(ActuallyImmutable.class);
* }
* });
*
* // in a test case
* MUTABILITY.assertImmutable(UsesActuallyImmutable.class); // this now passes
*
*
*
* Now classes which transitively depend on ActuallyImmutable
being
* correctly analysed will not result in false positive results.
*
* Testing Hardcoded Classes Directly
*
* Using the configuration from above, if we have the assertion:
*
*
* MUTABILITY.assertImmutable(ActuallyImmutable.class);
*
*
* The test case will fail. Even though it's hardcoded, if you test it directly,
* the result will reflect the real analysis. This is a deliberate choice, to
* alert you to the possibility that your choice to hardcode a result may no
* longer be valid. In this case you will want to write a an assertion which
* allows the specific reasons for failure. You can still use the same asserter
* you previously created for this, e.g.:
*
*
*
* MUTABILITY.assertInstancesOf(ActuallyImmutable.class,
* areImmutable(),
* // configure your "allowed reasons" here
* );
*
*
*
*
* @author Graham Allan / Grundlefleck at gmail dot com
*
* @see MutabilityMatchers
* @see AllowedReason
* @see AnalysisResult
* @see MutableReasonDetail
* @see IsImmutable
* @see Configuration
* @see Configurations#OUT_OF_THE_BOX_CONFIGURATION
* @see ConfigurationBuilder
* @see MutabilityReason
*/
public final class MutabilityAssert {
private MutabilityAssert() { }
private final static MutabilityAsserter defaultAsserter = MutabilityAsserter.configured(OUT_OF_THE_BOX_CONFIGURATION);
/**
* Checks that the given class is immutable, or fails with an {@link AssertionError}.
*
* Example:
*
* MutabilityAssert.assertImmutable(HopefullyImmutable.class);
*
*
* @see IsImmutable#IMMUTABLE
* @param expectedImmutableClass
*/
public static void assertImmutable(Class> expectedImmutableClass) {
defaultAsserter.assertImmutable(expectedImmutableClass);
}
/**
* Checks that the result of analysis satisfies the given {@link Matcher},
* or fails with an {@link AssertionError}.
*
* The given matcher will be invoked with the {@link AnalysisResult}
* produced by Mutability Detector's analysis of the given class. The most
* common matchers can be found at {@link MutabilityMatchers}.
*
* Example:
*
* MutabilityAssert.assertImmutable(HopefullyImmutable.class,
* MutabilityMatchers.areImmutable());
*
* MutabilityAssert.assertImmutable(HopefullyEffectivelyImmutable.class,
* MutabilityMatchers.areEffectivelyImmutable());
*
*
*
* @see MutabilityMatchers#areImmutable()
* @see MutabilityMatchers#areEffectivelyImmutable()
* @see Matcher
* @see AnalysisResult
* @see IsImmutable#IMMUTABLE
* @see IsImmutable#EFFECTIVELY_IMMUTABLE
*/
public static void assertInstancesOf(Class> clazz, Matcher mutabilityMatcher) {
defaultAsserter.assertInstancesOf(clazz, mutabilityMatcher);
}
/**
* Checks that the result of analysis satisfies the given {@link Matcher},
* while allowing mismatches in the form of an allowed reason, or fails with
* an {@link AssertionError}.
*
* The given matcher will be invoked with the {@link AnalysisResult}
* produced by Mutability Detector's analysis of the given class. The most
* common matchers can be found at {@link MutabilityMatchers}.
*
* The given allowed reason will be used to determine if any of the
* {@link MutableReasonDetail} attached to the {@link AnalysisResult} have
* been explicitly permitted by the unit test. If any of the reasons have
* not been allowed, an AssertionError will be thrown.
*
* Several out-of-the-box allowed reasons can be found at
* {@link AllowedReason}.
*
* Example:
*
*
*
* MutabilityAssert.assertImmutable(HopefullyImmutable.class,
* MutabilityMatchers.areImmutable(),
* AllowedReason.allowingForSubclassing());
*
*
*
*
*
* @see MutableReasonDetail
* @see AllowedReason
* @see AllowedReason#allowingForSubclassing()
* @see MutabilityMatchers#areImmutable()
*/
public static void assertInstancesOf(Class> clazz,
Matcher mutabilityMatcher,
Matcher allowing) {
defaultAsserter.assertInstancesOf(clazz, mutabilityMatcher, allowing);
}
/**
* Checks that the result of analysis satisfies the given {@link Matcher},
* while allowing mismatches in the form of allowed reasons, or fails with
* an {@link AssertionError}.
*
* The given matcher will be invoked with the {@link AnalysisResult}
* produced by Mutability Detector's analysis of the given class. The most
* common matchers can be found at {@link MutabilityMatchers}.
*
* The given allowed reason will be used to determine if any of the
* {@link MutableReasonDetail} attached to the {@link AnalysisResult} have
* been explicitly permitted by the unit test. If any of the reasons have
* not been allowed, an AssertionError will be thrown.
*
* Several out-of-the-box allowed reasons can be found at
* {@link AllowedReason}.
*
* Example:
*
*
* MutabilityAssert.assertImmutable(HopefullyImmutable.class,
* MutabilityMatchers.areImmutable(),
* AllowedReason.allowingForSubclassing(),
* AllowedReason.allowingNonFinalFields());
*
*
*
* @see MutableReasonDetail
* @see AllowedReason
* @see AllowedReason#allowingForSubclassing()
* @see MutabilityMatchers#areImmutable()
*/
public static void assertInstancesOf(Class> clazz,
Matcher mutabilityMatcher,
Matcher allowingFirst,
Matcher allowingSecond) {
defaultAsserter.assertInstancesOf(clazz, mutabilityMatcher, allowingFirst, allowingSecond);
}
/**
* Checks that the result of analysis satisfies the given {@link Matcher},
* while allowing mismatches in the form of allowed reasons, or fails with
* an {@link AssertionError}.
*
* Alternative version of
* {@link #assertInstancesOf(Class, Matcher, Matcher)} which takes more
* allowed reasons.
*
* @see MutableReasonDetail
* @see AllowedReason
* @see AllowedReason#allowingForSubclassing()
* @see AllowedReason#allowingNonFinalFields()
* @see MutabilityMatchers#areImmutable()
*/
public static void assertInstancesOf(Class> clazz,
Matcher mutabilityMatcher,
Matcher allowingFirst,
Matcher allowingSecond,
Matcher allowingThird) {
defaultAsserter.assertInstancesOf(clazz, mutabilityMatcher, allowingFirst, allowingSecond, allowingThird);
}
/**
* Checks that the result of analysis satisfies the given {@link Matcher},
* while allowing mismatches in the form of allowed reasons, or fails with
* an {@link AssertionError}.
*
* Alternative version of
* {@link #assertInstancesOf(Class, Matcher, Matcher)} which takes more
* allowed reasons.
*
* @see MutableReasonDetail
* @see AllowedReason
* @see AllowedReason#allowingForSubclassing()
* @see AllowedReason#allowingNonFinalFields()
* @see MutabilityMatchers#areImmutable()
*/
public static void assertInstancesOf(Class> clazz,
Matcher mutabilityMatcher,
Matcher allowingFirst,
Matcher allowingSecond,
Matcher allowingThird,
Matcher... allowingRest) {
defaultAsserter.assertInstancesOf(clazz,
mutabilityMatcher,
allowingFirst,
allowingSecond,
allowingThird,
allowingRest);
}
/**
* Checks that the result of analysis satisfies the given {@link Matcher},
* while allowing mismatches in the form of allowed reasons, or fails with
* an {@link AssertionError}.
*
* Alternative version of
* {@link #assertInstancesOf(Class, Matcher, Matcher)} which takes an
* iterable of allowed reasons.
*
* @see MutableReasonDetail
* @see AllowedReason
* @see AllowedReason#allowingForSubclassing()
* @see AllowedReason#allowingNonFinalFields()
* @see MutabilityMatchers#areImmutable()
*/
public static void assertInstancesOf(Class> clazz,
Matcher mutabilityMatcher,
Iterable> allowingAll) {
defaultAsserter.assertInstancesOf(clazz, mutabilityMatcher, allowingAll);
}
}