You now have the pieces to separate a business rule from its selection, wrap an optional behavior and check the resulting contract. This practice uses fresh fulfillment and testing requests, with the same narrow interfaces and assertion mechanics introduced in the unit. No new framework or pattern is required.
Treat the tests as consumers of the contract. A flat charge still needs the agreed zero-quantity behavior. An unknown factory name still needs an explicit failure signal. A failed assertion must not stop independent tests, and a new fixture must start without state from the prior test. Keep these guarantees visible while choosing your implementation. The returned counts and arrays are evidence of what ran; printed output alone doesn't satisfy a task.