package features.domain;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import features.domain.builders.Builders;
import features.domain.builders.ChildBuilder;
import features.domain.builders.ParentBuilder;
import joist.domain.orm.EagerLoading;
import joist.domain.uow.UoW;
import joist.jdbc.Jdbc;
public class ChildEagerLoadingTest extends AbstractFeaturesTest {
private ParentBuilder p1;
private ParentBuilder p2;
@Before
@Override
public void setUp() {
super.setUp();
this.p1 = Builders.aParent().name("p1");
this.p2 = Builders.aParent().name("p2");
this.commitAndReOpen();
}
@Test
public void testEagerLoadingIsEnabledByDefault() {
// should probably not be enabled by default ... we'll see what happens
Builders.aChild().name("c1").parent(this.p1);
Builders.aChild().name("c2").parent(this.p2);
this.commitAndReOpen();
this.p1.get(); // reload each parent
this.p2.get();
Jdbc.resetStats();
this.p1.get().getChilds(); // now reload each set of children
this.p2.get().getChilds();
Assert.assertEquals(1, Jdbc.numberOfQueries());
}
@Test
public void testEagerLoadingWhenDisabled() {
boolean wasEnabled = EagerLoading.isEnabled();
try {
EagerLoading.setEnabled(false);
Builders.aChild().name("c1").parent(this.p1);
Builders.aChild().name("c2").parent(this.p2);
this.commitAndReOpen();
this.p1.get(); // reload each parent
this.p2.get();
Jdbc.resetStats();
this.p1.get().getChilds(); // now reload each set of children
this.p2.get().getChilds(); // causes n+1 type behavior
Assert.assertEquals(2, Jdbc.numberOfQueries());
} finally {
EagerLoading.setEnabled(wasEnabled);
}
}
@Test
public void testEagerLoadingWhenDisabledForJustOneInstance() {
Builders.aChild().name("c1").parent(this.p1);
ChildBuilder c2 = Builders.aChild().name("c2").parent(this.p2);
Builders.aGrandChild().name("g3").child(c2).defaults();
this.commitAndReOpen();
this.p1.get(); // reload each parent
this.p2.get();
Jdbc.resetStats();
UoW.getEagerCache().doNotEagerlyLoadFor(this.p2.get());
this.p1.get().getChilds(); // now reload each set of children
this.p2.get().getChilds(); // causes n+1 type behavior
Assert.assertEquals(2, Jdbc.numberOfQueries());
Assert.assertEquals(1, c2.grandChilds().size()); // other collections still work
}
@Test
public void testEagerLoadingIsEnabledUsesOneQueryForAllChildren() {
Builders.aChild().name("c1").parent(this.p1);
Builders.aChild().name("c2").parent(this.p2);
this.commitAndReOpen();
this.p1.get(); // reload each parent
this.p2.get();
Jdbc.resetStats();
this.p1.get().getChilds(); // now reload each set of children
this.p2.get().getChilds();
Assert.assertEquals(1, Jdbc.numberOfQueries());
}
@Test
public void testEagerLoadingIsEnabledAndRemembersIfAParentDoesNotHaveAnyChildren() {
Builders.aChild().name("c1").parent(this.p1);
// Builders.aChild().name("c2").parent(this.p2); no child for p2
this.commitAndReOpen();
this.p1.get(); // reload each parent
this.p2.get();
Jdbc.resetStats();
this.p1.get().getChilds(); // now reload each set of children
this.p2.get().getChilds();
Assert.assertEquals(1, Jdbc.numberOfQueries());
}
@Test
public void testEagerLoadingIsEnabledAndReQueriesForNewlyLoadedParents() {
Builders.aChild().name("c1").parent(this.p1);
Builders.aChild().name("c2").parent(this.p2);
this.commitAndReOpen();
Jdbc.resetStats();
this.p1.get(); // reload only p1
this.p1.get().getChilds();
// now reload p2
this.p2.get();
// and ensure we can get its children
Assert.assertEquals(1, this.p2.childs().size());
// even though it took an extra query (p1, c1, p2, c2)
Assert.assertEquals(4, Jdbc.numberOfQueries());
}
@Test
public void testEagerLoadingOfParents() {
ChildBuilder c1 = Builders.aChild().name("c1").parent(this.p1);
ChildBuilder c2 = Builders.aChild().name("c2").parent(this.p2);
this.commitAndReOpen();
c1.get(); // reload each child
c2.get();
Jdbc.resetStats();
c1.parent(); // now reload each parent
c2.parent();
Assert.assertEquals(1, Jdbc.numberOfQueries());
}
@Test
public void testEagerLoadingOfParentsWhenDisabled() {
boolean wasEnabled = EagerLoading.isEnabled();
try {
EagerLoading.setEnabled(false);
ChildBuilder c1 = Builders.aChild().name("c1").parent(this.p1);
ChildBuilder c2 = Builders.aChild().name("c2").parent(this.p2);
this.commitAndReOpen();
c1.get(); // reload each child
c2.get();
Jdbc.resetStats();
c1.parent(); // now reload each parent
c2.parent();
Assert.assertEquals(2, Jdbc.numberOfQueries());
} finally {
EagerLoading.setEnabled(wasEnabled);
}
}
@Test
public void testEagerLoadingOfParentsForNewlyLoadedChildren() {
ChildBuilder c1 = Builders.aChild().name("c1").parent(this.p1);
ChildBuilder c2 = Builders.aChild().name("c2").parent(this.p2);
this.commitAndReOpen();
c1.get(); // reload only c1
Jdbc.resetStats();
c1.parent(); // now reload c1's parent
Assert.assertEquals(1, Jdbc.numberOfQueries());
c2.get(); // now bring c2 into the UoW
Jdbc.resetStats();
c2.parent(); // getting c2's parent will need another query
Assert.assertEquals(1, Jdbc.numberOfQueries());
}
@Test
public void testEagerLoadingDoesNotFailIfDisconnected() {
Parent p1 = this.p1.get();
this.commitAndReOpen();
try {
// p1 is disconnected now (UoW is open, but p1 is not in it)
Assert.assertEquals(0, p1.getChilds().size());
Assert.fail();
} catch (IllegalStateException ise) {
Assert.assertEquals("Instance has been disconnected from the UoW: Parent[1]", ise.getMessage());
}
}
}