Result Queueing Mechanism
Closed this issue · 3 comments
To do have proper support for unit testing, we need a system to queue up what results would come from what queries. This needs planning around how to support what kinds of queries (upsert vs sum vs findAll, etc).
Current Thinking
My idea at the moment is to have three functions on the FakeModel
object. One for queuing a successful query, and one for queuing a failure of some sort. The queue will be shared behind the scenes between the two functions so that the next call will return the next item in the queue regardless of whether it is a failure or success and handle it. This will allow testing for branching code based on failures, as well as detailed result testing.
The third function is a way to clear the queue so we can clean up after test failures and so we don't leave the objects polluted for the next test.
queueResult( result [, ... other returns] )
The idea here would be a single function to queue what the next returned result from a query on that object will be. For functions that return multiple values (e.g. findOrCreate
) more arguments will be accepted to enable additional return values. To the end user, this will be transparent, and default values will be used for any values that are not provided in this call.
For this, each query function call type will need to know to get the data it needs and how it can fallback to a default value.
queueFailure( ErrorObject )
This will queue the next query to reject the promise and return the given error object. This will require the error type from Sequelize to be in the Mock library so we can have good test support for if people handle specific errors from the DB in different ways. But an initial implementation can likely start with just accepting and passing along any error object until we get to v1.
clearQueue( )
Clears all future results for the queued results. This is to better enable test cleanup before and after tests run.
Slightly Updated Thinking
We'll need to have some additional options for how we want to handle queries and what we want to do with them. Switching the signature for the functions slightly
$queueQueryResult( result [, options] )
Alias: $qqr
The options parameter can be used to set return values like wasCreated
but also to mark if a result should have the default values in addition to any values that are included in the result
object.
$queueQueryFailure( ErrorObject [, options] )
Alias: $qqf
For now, the only options
will likely be if we should convert it to an error object (in which case we will convert it to a BaseError
unless it already is an Error
).
$clearQueryQueue( )
Alias: $cqq
, $qqc
Will function the same as before
Each mock Model
object will get a mock QueryInterface
object that can be used to queue results against that Model
in particular. Each Model.QueryInterface
will also inherit from a Sequelize.QueryInterface
on the mock Sequelize
interface it was defined against.
Queries run will use this priority for returning results
- The next result queued against
Model.QueryInterface
- If not available, the next result queued against
Sequelize.QueryInterface
(propagation can be disabled at either theModel
orSequelize
level) - If not available, any automatic
Model
building functionality will be relied on (current behavior) (can be disabled at theModel
orSequelize
level) - If none of the above are available, throw a
new EmptyQueryQueueError()
error.
All queries will follow this basic priority in returning results. Automatic return and propagation will be enabled by default to enable the smoothest upgrade path.