-
Notifications
You must be signed in to change notification settings - Fork 43
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Can't test processor function which enqueues another job #51
Comments
Do you know of any good examples of Go network libraries/APIs which have built in support for stubbing/mocking/handling this type of usecase? It would really help inform me about what's possible here. So I'm trying to think through the various possibilities:
counts, err := executor.ExecuteWithCounts(job, myProcessor.Process)
assert.EqualValues(t, 1, len(counts.PushedJobs())) |
There may be more elegant ways to do it, but your 2) possibility is exactly what we do to stub out interacting with Kafka in our unit tests. We use github.com/segmentio/kafka-go to produce events to Kafka. First we define a generic message writing interface like so:
Our Faktory job processing structs, which in addition to processing jobs from Faktory, also produce events to Kafka. They have fields which hold these
In our unit tests, we declare up a mock producer which just collects the messages sent to it (and has a flag to simulate errors).
And then set these mock producers on our Faktory job processing structs:
In each test example we can assert that a message was produced to Kafka like so:
Compare that to the real setup where we use actual kafka message writers which match the same
I copied all of that from real code and changed the names to protect the innocent, so if something doesn't match up sorry about that, but hopefully you get the idea. |
The quickest solution is refactoring and abstracting. With this route, I think you can solve your problem. func (p *MyProcessor) Process(ctx context.Context, args ...interface{}) error {
// enqueue a job for post-processing
// this code doesn't need to be in the With block
jobArgument := make(map[string]interface{})
jobArgument["id"] = theID
jobArgs := []interface{}{jobArgument}
postProcessingJob := faktory.NewJob("post-processing", jobArgs...)
// create a new wrapper abstraction which understands if we are in test mode
// and provides a Push(Job) method.
myWrapper := testWrapper(worker.HelperFor(ctx))
ppjerr := myWrapper.Push(postProcessingJob) You fill in the I'm still pondering how to add test mode. Right now I'm thinking it would be a boolean on TestExecutor which would capture Helper interface calls rather than call the underlying Client. It wouldn't abstract |
See #52 for initial prototype. |
I have a job processing function that needs to enqueue another job when it's done with it's work. As noted in the FAQ I'm using the
helper.With()
function to get a handle to afaktory.Client
from the pool to push the new job. For example:In the unit tests for MyProcessor, I'm using the
worker.NewTestExecutor(pool)
functionto send test jobs to MyProcessor. For example (test cruft removed):
The enqueueing of the second job during the test is returning an error because it appears as though it's attempting to connect to Faktory to push the job, despite the fact I'm using the test executor.
post processing job job error: dial tcp [::1]:7419: connect: connection refused
How exactly do I unit test processor functions which enqueue another job without having it actually try to connect to Faktory? The structure of the code makes it awkward (impossible?) to stub/mock the faktory.Client needed to push the job.
The text was updated successfully, but these errors were encountered: