/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
package org.apache.isis.core.unittestsupport.bidir;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.Matchers.greaterThan;
import static org.junit.Assert.assertThat;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.Set;
import javax.jdo.annotations.Persistent;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableMap;
import org.hamcrest.Matchers;
import org.reflections.ReflectionUtils;
import org.reflections.Reflections;
import org.apache.isis.core.unittestsupport.AbstractApplyToAllContractTest;
import org.apache.isis.core.unittestsupport.utils.CollectUtils;
import org.apache.isis.core.unittestsupport.utils.ReflectUtils;
import org.apache.isis.core.unittestsupport.utils.StringUtils;
public abstract class BidirectionalRelationshipContractTestAbstract extends AbstractApplyToAllContractTest implements Instantiators {
private final InstantiatorMap instantiatorMap;
protected BidirectionalRelationshipContractTestAbstract(
final String packagePrefix,
ImmutableMap<Class<?>,Instantiator> instantiatorsByClass) {
super(packagePrefix);
instantiatorMap = new InstantiatorMap(instantiatorsByClass);
}
@Override
protected void applyContractTest(Class<?> entityType) {
final Set<Field> mappedByFields = ReflectionUtils.getAllFields(entityType, ReflectUtils.persistentMappedBy);
for (Field mappedByField : mappedByFields) {
final Parent p = new Parent();
p.entityType = entityType;
p.childField = mappedByField;
try {
out.println("processing " + p.entityType.getSimpleName() + "#" + p.childField.getName());
out.incrementIndent();
process(p);
} finally {
out.decrementIndent();
}
}
}
private void process(Parent p) {
// mappedBy
final Persistent persistentAnnotation = p.childField.getAnnotation(Persistent.class);
p.mappedBy = persistentAnnotation.mappedBy();
// getMethod
final String getMethod = StringUtils.methodNamed("get", p.childField);
final Set<Method> getMethods = ReflectionUtils.getAllMethods(p.entityType, withConcreteMethodNamed(getMethod));
assertThat(p.desc() + ": no unique getXxx() method:" + getMethods , getMethods.size(), is(greaterThan(0)));
p.getMethod = CollectUtils.firstIn(getMethods);
final Child c = new Child();
final Class<?> returnType = p.getMethod.getReturnType();
if(Collection.class.isAssignableFrom(returnType)) {
// addToMethod
final String addToMethod = StringUtils.methodNamed("addTo", p.childField);
final Set<Method> addToMethods = ReflectionUtils.getAllMethods(p.entityType,
Predicates.and(withConcreteMethodNamed(addToMethod), ReflectionUtils.withParametersCount(1), ReflectUtils.withEntityParameter()));
if(addToMethods.size() != 1) {
// just skip
out.println("no addToXxx() method in parent");
return;
}
p.addToMethod = CollectUtils.firstIn(addToMethods);
// removeFromMethod
final String removeFromMethod = StringUtils.methodNamed("removeFrom", p.childField);
final Set<Method> removeFromMethods = ReflectionUtils.getAllMethods(p.entityType,
Predicates.and(withConcreteMethodNamed(removeFromMethod), ReflectionUtils.withParametersCount(1), ReflectUtils.withEntityParameter()));
if(removeFromMethods.size() != 1) {
// just skip
out.println("no removeFromXxx() method in parent");
return;
}
p.removeFromMethod = CollectUtils.firstIn(removeFromMethods);
// child's entityType
final Class<?> addToParameterType = p.addToMethod.getParameterTypes()[0];
final Class<?> removeFromParameterType = p.removeFromMethod.getParameterTypes()[0];
assertThat(p.desc() + ": " + p.addToMethod.getName() + " and " + p.removeFromMethod.getName() + " should have the same parameter type",
addToParameterType == removeFromParameterType, is(true));
c.entityType = addToParameterType;
} else {
// modify
String modifyMethod = StringUtils.methodNamed("modify", p.childField);
final Set<Method> modifyMethods = ReflectionUtils.getAllMethods(p.entityType,
Predicates.and(withConcreteMethodNamed(modifyMethod), ReflectionUtils.withParametersCount(1), ReflectUtils.withEntityParameter()));
if(modifyMethods.size() != 1) {
// just skip
out.println("no modifyXxx() method in parent");
return;
}
p.modifyMethod = CollectUtils.firstIn(modifyMethods);
// clear
String clearMethod = StringUtils.methodNamed("clear", p.childField);
final Set<Method> clearMethods = ReflectionUtils.getAllMethods(p.entityType,
Predicates.and(withConcreteMethodNamed(clearMethod), ReflectionUtils.withParametersCount(0)));
if(clearMethods.size() != 1) {
// just skip
out.println("no clearXxx() method in parent");
return;
}
p.clearMethod = CollectUtils.firstIn(clearMethods);
// child's entityType
c.entityType = p.modifyMethod.getParameterTypes()[0];
}
final Instantiator parentInstantiator = instantiatorFor(p.entityType);
if(parentInstantiator == null) {
out.println("no instantiator for " + p.entityType.getName());
// just skip
return;
}
final Instantiator childInstantiator = instantiatorFor(c.entityType);
if(childInstantiator == null) {
out.println("no instantiator for " + c.entityType.getName());
// just skip
return;
}
process(p, c);
}
private static Predicate<Method> withConcreteMethodNamed(final String getMethod) {
return Predicates.and(ReflectionUtils.withName(getMethod), new Predicate<Method>(){
public boolean apply(Method m) {
return !m.isSynthetic() && !Modifier.isAbstract(m.getModifiers());
}
});
}
private Instantiator instantiatorFor(final Class<?> cls) {
Instantiator instantiator = instantiatorMap.get(cls);
if(instantiator != null) {
return instantiator;
}
instantiator = doInstantiatorFor(cls);
instantiator = instantiatorMap.put(cls, instantiator);
return instantiator != Instantiator.NOOP? instantiator: null;
}
/**
* Default just tries to use the {@link InstantiatorSimple};
* subclasses can override with more sophisticated implementations if required.
*/
protected Instantiator doInstantiatorFor(final Class<?> cls) {
return new InstantiatorSimple(cls);
}
private void process(Parent p, Child c) {
// mappedBy field
final Set<Field> parentFields = ReflectionUtils.getAllFields(c.entityType, Predicates.and(ReflectionUtils.withName(p.mappedBy), ReflectUtils.withTypeAssignableFrom(p.entityType)));
assertThat(c.entityType.getName()+ ": could not locate '" + p.mappedBy + "' field, returning supertype of " + p.entityType.getSimpleName() +", (as per @Persistent(mappedBy=...) in parent "+ p.entityType.getSimpleName()+")", parentFields.size(), is(1));
c.parentField = CollectUtils.firstIn(parentFields);
// getter
String getterMethod = StringUtils.methodNamed("get", c.parentField);
final Set<Method> getterMethods = ReflectionUtils.getAllMethods(c.entityType,
Predicates.and(withConcreteMethodNamed(getterMethod), ReflectionUtils.withParametersCount(0), ReflectUtils.withReturnTypeAssignableFrom(p.entityType)));
assertThat(p.descRel(c) +": could not locate getter " + getterMethod + "() returning supertype of " + p.entityType.getSimpleName(), getterMethods.size(), is(1));
c.getMethod = CollectUtils.firstIn(getterMethods);
// modify
String modifyMethod = StringUtils.methodNamed("modify", c.parentField);
final Set<Method> modifyMethods = ReflectionUtils.getAllMethods(c.entityType,
Predicates.and(withConcreteMethodNamed(modifyMethod), ReflectionUtils.withParametersCount(1), ReflectUtils.withParametersAssignableFrom(p.entityType)));
if(modifyMethods.size() != 1) {
// just skip
out.println("no modifyXxx() method in child");
return;
}
c.modifyMethod = CollectUtils.firstIn(modifyMethods);
// clear
String clearMethod = StringUtils.methodNamed("clear", c.parentField);
final Set<Method> clearMethods = ReflectionUtils.getAllMethods(c.entityType,
Predicates.and(withConcreteMethodNamed(clearMethod), ReflectionUtils.withParametersCount(0)));
if(clearMethods.size() != 1) {
// just skip
out.println("no clearXxx() method in child");
return;
}
c.clearMethod = CollectUtils.firstIn(clearMethods);
exercise(p, c);
}
@Override
public Object newInstance(final Class<?> entityType) {
final Instantiator instantiator = instantiatorFor(entityType);
return instantiator.instantiate();
}
private static String assertDesc(Parent p, Child c, String methodDesc, String testDesc) {
return p.descRel(c) +": " + methodDesc + ": " + testDesc;
}
private void exercise(Parent p, Child c) {
out.println("exercising " + p.descRel(c));
out.incrementIndent();
try {
if(p.addToMethod != null) {
// 1:m
// add
oneToManyParentAddTo(p, c);
oneToManyParentAddToWhenAlreadyChild(p, c);
oneToManyParentAddToWhenNull(p, c);
oneToManyChildModify(p, c);
oneToManyChildModifyWhenAlreadyParent(p, c);
oneToManyChildModifyWhenNull(p, c);
// move (update)
oneToManyChildModifyToNewParent(p, c);
oneToManyChildModifyToExistingParent(p, c);
// delete
oneToManyParentRemoveFrom(p, c);
oneToManyParentRemoveFromWhenNotAssociated(p, c);
oneToManyParentRemoveFromWhenNull(p, c);
oneToManyChildClear(p, c);
oneToManyChildClearWhenNotAssociated(p, c);
} else {
// 1:1
// add
oneToOneParentModify(p, c);
oneToOneParentModifyWhenAlreadyChild(p, c);
oneToOneParentModifyWhenNull(p, c);
oneToOneChildModify(p, c);
oneToOneChildModifyWhenAlreadyParent(p, c);
oneToOneChildModifyWhenNull(p, c);
// move (update)
oneToOneChildModifyToNewParent(p, c);
oneToOneChildModifyToExistingParent(p, c);
// delete
oneToOneParentClear(p, c);
oneToOneChildClear(p, c);
oneToOneChildClearWhenNotAssociated(p, c);
}
} finally {
out.decrementIndent();
}
}
////////////////
// 1:m
////////////////
private void oneToManyParentAddTo(Parent p, Child c) {
final String methodDesc = "oneToManyParentAddTo";
out.println(methodDesc);
// given
Object parent1 = p.newParent(this);
Object child1 = c.newChild(this);
// when
p.addToChildren(parent1, child1);
// then
assertThat(assertDesc(p,c,methodDesc,"parent contains child"), p.getChildren(parent1), Matchers.containsInAnyOrder(child1));
assertThat(assertDesc(p,c,methodDesc,"child references parent"), c.getParent(child1), is(parent1));
}
private void oneToManyParentAddToWhenAlreadyChild(Parent p, Child c) {
final String methodDesc = "oneToManyParentAddToWhenAlreadyChild";
out.println(methodDesc);
// given
Object parent1 = p.newParent(this);
Object child1 = c.newChild(this);
// given
p.addToChildren(parent1, child1);
// when
p.addToChildren(parent1, child1);
// then
assertThat(assertDesc(p,c,methodDesc,"parent still contains child"), p.getChildren(parent1), Matchers.containsInAnyOrder(child1));
assertThat(assertDesc(p,c,methodDesc,"child still references parent"), c.getParent(child1), is(parent1));
}
private void oneToManyParentAddToWhenNull(Parent p, Child c) {
final String methodDesc = "oneToManyParentAddToWhenNull";
out.println(methodDesc);
// given
Object parent1 = p.newParent(this);
// when
p.addToChildren(parent1, null);
// then
assertThat(assertDesc(p,c,methodDesc,"parent does not have any children"), p.getChildren(parent1).isEmpty(), is(true));
}
private void oneToManyChildModify(Parent p, Child c) {
final String methodDesc = "oneToManyChildModify";
out.println(methodDesc);
// given
Object parent1 = p.newParent(this);
Object child1 = c.newChild(this);
// when
c.modifyParent(child1, parent1);
// then
assertThat(assertDesc(p,c,methodDesc,"parent contains child"), p.getChildren(parent1), Matchers.containsInAnyOrder(child1));
assertThat(assertDesc(p,c,methodDesc,"child references parent"), c.getParent(child1), is(parent1));
}
private void oneToManyChildModifyWhenAlreadyParent(Parent p, Child c) {
final String methodDesc = "oneToManyChildModifyWhenAlreadyParent";
out.println(methodDesc);
// given
Object parent1 = p.newParent(this);
Object child1 = c.newChild(this);
c.modifyParent(child1, parent1);
// when
c.modifyParent(child1, parent1);
// then
assertThat(assertDesc(p,c,methodDesc,"parent still contains child"), p.getChildren(parent1), Matchers.containsInAnyOrder(child1));
assertThat(assertDesc(p,c,methodDesc,"child still references parent"), c.getParent(child1), is(parent1));
}
private void oneToManyChildModifyWhenNull(Parent p, Child c) {
final String methodDesc = "oneToManyChildModifyWhenNull";
out.println(methodDesc);
// given
Object child1 = c.newChild(this);
// when
c.modifyParent(child1, null);
// then
assertThat(assertDesc(p,c,methodDesc,"child does not reference any parent"), c.getParent(child1), is(nullValue()));
}
private void oneToManyChildModifyToNewParent(Parent p, Child c) {
final String methodDesc = "oneToManyChildModifyToNewParent";
out.println(methodDesc);
// given
Object parent1 = p.newParent(this);
Object parent2 = p.newParent(this);
Object child1 = c.newChild(this);
Object child2 = c.newChild(this);
p.addToChildren(parent1, child1);
p.addToChildren(parent2, child2);
// when
c.modifyParent(child1, parent2);
// then
assertThat(assertDesc(p,c,methodDesc,"parent 1 no longer has any children"), p.getChildren(parent1).isEmpty(), is(true));
assertThat(assertDesc(p,c,methodDesc,"parent 2 now has both children"), p.getChildren(parent2), Matchers.containsInAnyOrder(child1, child2));
assertThat(assertDesc(p,c,methodDesc,"child 1 now references parent 2"), c.getParent(child1), is(parent2));
assertThat(assertDesc(p,c,methodDesc,"child 2 still references parent 2"), c.getParent(child2), is(parent2));
}
private void oneToManyChildModifyToExistingParent(Parent p, Child c) {
final String methodDesc = "oneToManyChildModifyToExistingParent";
out.println(methodDesc);
// given
Object parent1 = p.newParent(this);
Object parent2 = p.newParent(this);
Object child1 = c.newChild(this);
Object child2 = c.newChild(this);
p.addToChildren(parent1, child1);
p.addToChildren(parent2, child2);
// when
c.modifyParent(child1, parent1);
// then
assertThat(assertDesc(p,c,methodDesc,"parent 1 still contains child 1"), p.getChildren(parent1), Matchers.containsInAnyOrder(child1));
assertThat(assertDesc(p,c,methodDesc,"parent 2 still contains child 2"), p.getChildren(parent2), Matchers.containsInAnyOrder(child2));
assertThat(assertDesc(p,c,methodDesc,"child 1 still references parent 1"), c.getParent(child1), is(parent1));
assertThat(assertDesc(p,c,methodDesc,"child 2 still references parent 2"), c.getParent(child2), is(parent2));
}
private void oneToManyParentRemoveFrom(Parent p, Child c) {
final String methodDesc = "oneToManyParentRemoveFrom";
out.println(methodDesc);
// given
Object parent1 = p.newParent(this);
Object child1 = c.newChild(this);
p.addToChildren(parent1, child1);
// when
p.removeFromChildren(parent1, child1);
// then
assertThat(assertDesc(p,c,methodDesc,"parent no longer contains child"), p.getChildren(parent1).isEmpty(), is(true));
assertThat(assertDesc(p,c,methodDesc,"child no longer references parent"), c.getParent(child1), is(nullValue()));
}
private void oneToManyParentRemoveFromWhenNull(Parent p, Child c) {
final String methodDesc = "oneToManyParentRemoveFromWhenNull";
out.println(methodDesc);
// given
Object parent1 = p.newParent(this);
Object child1 = c.newChild(this);
p.addToChildren(parent1, child1);
// when
p.removeFromChildren(parent1, null);
// then
assertThat(assertDesc(p,c,methodDesc,"parent still contains child"), p.getChildren(parent1), Matchers.containsInAnyOrder(child1));
assertThat(assertDesc(p,c,methodDesc,"child still references parent"), c.getParent(child1), is(parent1));
}
private void oneToManyParentRemoveFromWhenNotAssociated(Parent p, Child c) {
final String methodDesc = "oneToManyParentRemoveFromWhenNotAssociated";
out.println(methodDesc);
// given
Object parent1 = p.newParent(this);
Object child1 = c.newChild(this);
Object child2 = c.newChild(this);
p.addToChildren(parent1, child1);
// when
p.removeFromChildren(parent1, child2);
// then
assertThat(assertDesc(p,c,methodDesc,"parent still contains child"), p.getChildren(parent1), Matchers.containsInAnyOrder(child1));
assertThat(assertDesc(p,c,methodDesc,"child still references parent"), c.getParent(child1), is(parent1));
}
private void oneToManyChildClear(Parent p, Child c) {
final String methodDesc = "oneToManyChildClear";
out.println(methodDesc);
// given
Object parent1 = p.newParent(this);
Object child1 = c.newChild(this);
p.addToChildren(parent1, child1);
// when
c.clearParent(child1);
// then
assertThat(assertDesc(p,c,methodDesc,"parent no longer contains child"), p.getChildren(parent1).isEmpty(), is(true));
assertThat(assertDesc(p,c,methodDesc,"child no longer references parent"), c.getParent(child1), is(nullValue()));
}
private void oneToManyChildClearWhenNotAssociated(Parent p, Child c) {
final String methodDesc = "oneToManyChildClearWhenNotAssociated";
out.println(methodDesc);
// given
Object parent1 = p.newParent(this);
Object child1 = c.newChild(this);
// when
c.clearParent(child1);
// then
assertThat(assertDesc(p,c,methodDesc,"parent still does not reference child"), p.getChildren(parent1).isEmpty(), is(true));
assertThat(assertDesc(p,c,methodDesc,"child still does not reference parent"), c.getParent(child1), is(nullValue()));
}
////////////////
// 1:1
////////////////
private void oneToOneParentModify(Parent p, Child c) {
final String methodDesc = "oneToOneParentModify";
out.println(methodDesc);
// given
Object parent1 = p.newParent(this);
Object child1 = c.newChild(this);
// when
p.modifyChild(parent1, child1);
// then
assertThat(assertDesc(p,c,methodDesc,"parent references child"),p.getChild(parent1), is(child1));
assertThat(assertDesc(p,c,methodDesc,"child references parent"), c.getParent(child1), is(parent1));
}
private void oneToOneParentModifyWhenAlreadyChild(Parent p, Child c) {
final String methodDesc = "oneToOneParentModifyWhenAlreadyChild";
out.println(methodDesc);
// given
Object parent1 = p.newParent(this);
Object child1 = c.newChild(this);
p.modifyChild(parent1, child1);
// when
p.modifyChild(parent1, child1);
// then
assertThat(assertDesc(p,c,methodDesc,"parent still references child"), p.getChild(parent1), is(child1));
assertThat(assertDesc(p,c,methodDesc,"child still references parent"), c.getParent(child1), is(parent1));
}
private void oneToOneParentModifyWhenNull(Parent p, Child c) {
final String methodDesc = "oneToOneParentModifyWhenNull";
out.println(methodDesc);
// given
Object parent1 = p.newParent(this);
// when
p.modifyChild(parent1, null);
// then
assertThat(assertDesc(p,c,methodDesc,"parent still references child"), p.getChild(parent1), is(nullValue()));
}
private void oneToOneChildModify(Parent p, Child c) {
final String methodDesc = "oneToOneChildModify";
out.println(methodDesc);
// given
Object parent1 = p.newParent(this);
Object child1 = c.newChild(this);
// when
c.modifyParent(child1, parent1);
// then
assertThat(assertDesc(p,c,methodDesc,"parent references child"), p.getChild(parent1), is(child1));
assertThat(assertDesc(p,c,methodDesc,"child references parent"), c.getParent(child1), is(parent1));
}
private void oneToOneChildModifyWhenAlreadyParent(Parent p, Child c) {
final String methodDesc = "oneToOneChildModifyWhenAlreadyParent";
out.println(methodDesc);
// given
Object parent1 = p.newParent(this);
Object child1 = c.newChild(this);
c.modifyParent(child1, parent1);
// when
c.modifyParent(child1, parent1);
// then
assertThat(assertDesc(p,c,methodDesc,"parent still references child"), p.getChild(parent1), is(child1));
assertThat(assertDesc(p,c,methodDesc,"child still references parent"), c.getParent(child1), is(parent1));
}
private void oneToOneChildModifyWhenNull(Parent p, Child c) {
final String methodDesc = "oneToOneChildModifyWhenNull";
out.println(methodDesc);
// given
Object child1 = c.newChild(this);
// when
c.modifyParent(child1, null);
// then
assertThat(assertDesc(p,c,methodDesc,"child still has no parent"), c.getParent(child1), is(nullValue()));
}
private void oneToOneChildModifyToNewParent(Parent p, Child c) {
final String methodDesc = "oneToOneChildModifyToNewParent";
out.println(methodDesc);
// given
Object parent1 = p.newParent(this);
Object parent2 = p.newParent(this);
Object child1 = c.newChild(this);
Object child2 = c.newChild(this);
p.modifyChild(parent1, child1);
p.modifyChild(parent2, child2);
// when
c.modifyParent(child1, parent2);
// then
assertThat(assertDesc(p,c,methodDesc,"parent 1 no longer references child 1"), p.getChild(parent1), is(nullValue()));
assertThat(assertDesc(p,c,methodDesc,"parent 2 now references child 1"), p.getChild(parent2), is(child1));
assertThat(assertDesc(p,c,methodDesc,"child 1 now references parent 2"), c.getParent(child1), is(parent2));
assertThat(assertDesc(p,c,methodDesc,"child 2, as a side-effect, no longer references parent 2"), c.getParent(child2), is(nullValue()));
}
private void oneToOneChildModifyToExistingParent(Parent p, Child c) {
final String methodDesc = "oneToOneChildModifyToExistingParent";
out.println(methodDesc);
// given
Object parent1 = p.newParent(this);
Object parent2 = p.newParent(this);
Object child1 = c.newChild(this);
Object child2 = c.newChild(this);
p.modifyChild(parent1, child1);
p.modifyChild(parent2, child2);
// when
c.modifyParent(child1, parent1);
// then
assertThat(assertDesc(p,c,methodDesc,"parent 1 still references child 1"), p.getChild(parent1), is(child1));
assertThat(assertDesc(p,c,methodDesc,"parent 2 still references child 2"), p.getChild(parent2), is(child2));
assertThat(assertDesc(p,c,methodDesc,"child 1 still references parent 1"), c.getParent(child1), is(parent1));
assertThat(assertDesc(p,c,methodDesc,"child 2 still references parent 2"), c.getParent(child2), is(parent2));
}
private void oneToOneParentClear(Parent p, Child c) {
final String methodDesc = "oneToOneParentClear";
out.println(methodDesc);
// given
Object parent1 = p.newParent(this);
Object child1 = c.newChild(this);
p.modifyChild(parent1, child1);
// when
p.clearChild(parent1);
// then
assertThat(assertDesc(p,c,methodDesc,"parent no longer references child"), p.getChild(parent1), is(nullValue()));
assertThat(assertDesc(p,c,methodDesc,"child no longer references parent"), c.getParent(child1), is(nullValue()));
}
private void oneToOneChildClear(Parent p, Child c) {
final String methodDesc = "oneToOneChildClear";
out.println(methodDesc);
// given
Object parent1 = p.newParent(this);
Object child1 = c.newChild(this);
p.modifyChild(parent1, child1);
// when
c.clearParent(child1);
// then
assertThat(assertDesc(p,c,methodDesc,"parent no longer references child"), p.getChild(parent1), is(nullValue()));
assertThat(assertDesc(p,c,methodDesc,"child no longer references parent"), c.getParent(child1), is(nullValue()));
}
private void oneToOneChildClearWhenNotAssociated(Parent p, Child c) {
final String methodDesc = "oneToOneChildClearWhenNotAssociated";
out.println(methodDesc);
// given
Object parent1 = p.newParent(this);
Object child1 = c.newChild(this);
// when
c.clearParent(child1);
// then
assertThat(assertDesc(p,c,methodDesc,"parent still does not reference child"), p.getChild(parent1), is(nullValue()));
assertThat(assertDesc(p,c,methodDesc,"child still does not reference parent"), c.getParent(child1), is(nullValue()));
}
}