// Given a monic and an arrow to premultiply it, check we can factorize this out again via the
  // subobject classifier and its induced pullback
  @Test
  public void testSubobjectClassifier() {
    ARROW monicPrefix = fixtures.arrowBubToFoo();
    ARROW monic = fixtures.arrowMonicFooToBar();

    SubobjectClassifier<DOT, ARROW> classifier = _topos.getSubobjectClassifier();
    ARROW truth = classifier.getTruth();
    TerminatorDiagram<DOT, ARROW> tDgm = _topos.getTerminatorDiagram();
    DOT terminator = tDgm.getTerminator();
    assertTrue(terminator == truth.getSource());

    assertTrue(monicPrefix.getTarget() == monic.getSource());
    PullbackDiagram<DOT, ARROW> pullback = classifier.pullbackMonic(monic);

    // Verify that this really is a pullback diagram and can factor out the monic.
    ARROW north = pullback.getNorth();
    ARROW south = pullback.getSouth();
    ARROW west = pullback.getWest();
    ARROW east = pullback.getEast();
    assertTrue(north.getSource() == west.getSource());
    assertTrue(north.getTarget() == east.getSource());
    assertTrue(south.getSource() == west.getTarget());
    assertTrue(south.getTarget() == east.getTarget());
    assertTrue(east.compose(north).equals(south.compose(west)));
    // it's a commutative square: now, are the right bits in place?
    assertTrue(south == truth); // seems reasonable to insist on strict equality here
    assertTrue(north == monic);

    // pull back the composition...
    ARROW composition = monic.compose(monicPrefix);
    ARROW constant = tDgm.getConstantArrow(composition.getSource());
    // sanity check: just make sure it can be pulled back...
    assertTrue(east.compose(composition).equals(south.compose(constant)));
    List<ARROW> commutingArrows = new ArrayList<ARROW>();
    commutingArrows.add(composition);
    commutingArrows.add(constant);
    ARROW factor =
        pullback.factorize(commutingArrows); // should have extract the original prefix arrow
    assertTrue(monicPrefix.equals(factor));
  }