diff --git a/SUMMARY.md b/SUMMARY.md index 1633d1e..eb60eef 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -9,6 +9,7 @@ * [Code of Ethics](prestd/code-of-ethics.md) * [Get pREST](get-prest/README.md) * [Development Guide](get-prest/development-guide.md) + * [Mock Adapter](get-prest/mock-adapter.md) * [Start with Docker]() * [Start with Golang](get-prest/start-with-golang.md) * [Start with Homebrew](get-prest/start-with-homebrew.md) diff --git a/get-prest/development-guide.md b/get-prest/development-guide.md index 95e3cf8..ef21d9a 100644 --- a/get-prest/development-guide.md +++ b/get-prest/development-guide.md @@ -135,6 +135,8 @@ That's it, you have a way to validate the project running locally, and to test o pREST's unit tests depend on a working Postgres database for SQL query execution, to simplify the preparation of the local environment we use docker (and docker-compose) to upload the environment with Postgres. +For tests that do not need a real PostgreSQL connection, use the [mock adapter](mock-adapter.md) to queue scanner responses and exercise adapter-backed code paths in memory. + **all tests:** ```sh diff --git a/get-prest/mock-adapter.md b/get-prest/mock-adapter.md new file mode 100644 index 0000000..1984d67 --- /dev/null +++ b/get-prest/mock-adapter.md @@ -0,0 +1,86 @@ +# Mock Adapter + +The `github.com/prest/prest/v2/adapters/mock` package provides a lightweight +implementation of the `adapters.Adapter` interface for tests. It avoids a real +PostgreSQL connection and returns queued scanner responses from memory. + +Use it when a controller, middleware, router, or other adapter-backed test needs +pREST behavior but does not need database-specific behavior. + +## Basic usage + +Create the adapter with the current test, then assign it to the global pREST +configuration used by the code under test: + +```go +import ( + "testing" + + "github.com/prest/prest/v2/adapters/mock" + "github.com/prest/prest/v2/config" +) + +func TestHandler(t *testing.T) { + adapter := mock.New(t) + config.PrestConf.Adapter = adapter + + adapter.AddItem([]byte(`[{"id":1,"name":"prest"}]`), nil, false) + + // Run code that calls config.PrestConf.Adapter.Query(...) +} +``` + +`mock.New(t)` also registers a `database/sql` driver named `mock`. The +transaction helpers use a mock DSN named `prest`, so tests can exercise +transaction paths without opening a network connection. + +### Queued responses + +The mock adapter stores responses in `Mock.Items`. Each query-like or +mutation-like method consumes the next queued item and returns it as a +`scanner.PrestScanner`. + +Queue items with `AddItem`: + +```go +adapter.AddItem(responseBody, responseError, isCount) +``` + +The arguments map to `mock.Item` fields: + +* `responseBody`: JSON bytes returned by the scanner. +* `responseError`: error exposed by the scanner. +* `isCount`: count metadata returned by clause helpers such as `DatabaseClause` + and `SchemaClause`. + +Add one item for each adapter operation the test expects. If code calls a +mocked operation that consumes a response and no items are queued, the mock +fails the test with `do not have any operations to perform`. + +### Permissions + +`TablePermissions` reads `config.PrestConf.AccessConf`. When access +restrictions are disabled, it returns `true`. When restrictions are enabled, it +checks table-level permissions first and then user-specific table permissions +when a user name is provided. + +This lets tests cover authorization behavior without a database fixture: + +```go +config.PrestConf.AccessConf.Restrict = true +config.PrestConf.AccessConf.Tables = []config.TablesConf{ + {Name: "books", Permissions: []string{"read"}}, +} + +if !adapter.TablePermissions("books", "read", "") { + t.Fatal("expected read access") +} +``` + +### Generated mocks + +This package is different from `adapters/mockgen`. The `mockgen` package is +generated by GoMock from the adapter interfaces and is useful when a test needs +strict call expectations. The `mock` package is hand-written and is better for +controller-style tests that need scanner responses and simple permission +behavior.