BlinkUX/sequelize-mock

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

  1. The next result queued against Model.QueryInterface
  2. If not available, the next result queued against Sequelize.QueryInterface (propagation can be disabled at either the Model or Sequelize level)
  3. If not available, any automatic Model building functionality will be relied on (current behavior) (can be disabled at the Model or Sequelize level)
  4. 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.