I just rolled my own mocked Celery objects. I have mocked Groups, Chords, Chains, and Signatures, mocked Celery backend, and mocked dispatch of tasks. Everything runs eagerly because it's all just running locally in the same thread, but the workflow still runs properly-- the output of one task is fed into the next task, the tasks are updated, etc.
I actually pass Celery and the functions like `signature`, `chain`, etc as a tuple into my service layer functions.
It's mostly just to test that the piping of the workflow is set up correctly so I don't find out that my args are swapped later during integration tests.