Skip to content
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

Split high-level generated interface from low-level direct API mapping #87

Closed
nfx opened this issue Sep 14, 2022 · 0 comments · Fixed by #131
Closed

Split high-level generated interface from low-level direct API mapping #87

nfx opened this issue Sep 14, 2022 · 0 comments · Fixed by #131

Comments

@nfx
Copy link
Contributor

nfx commented Sep 14, 2022

No description provided.

nfx added a commit that referenced this issue Oct 21, 2022
# Goal: present consistent entity listing for the end-user

Only 30% of APIs have pagination, though there are two different
implementations of it. This PR proposes generating wrapper methods to
return consistent type for a collection of all results. It also adds
frequently used wrappers, like name-to-id mapping, which could later be
used to generate client-level upserts.

Decisions to discuss:

## Return type: slice vs iterator

* Current implementation proposes returning slice + error
* theoretically, with added complexity, we can move to iterator + error
implementation, though Go ecosystem didn't settle on the standard
iterator yet: golang/go#54245
* other ecosystems, like Python, Java, and JavaScript should lean
towards iterators

## Naming: ListQueriesAll (suffix) vs ListAllQueries (infix) vs all
methods returning slices (might be invasive)

* current template has "All" name suffix for methods returning all
results
* 18% of APIs return slice from the platform.
* 36% of APIs return all results, but in a single-field response.

### Out of scope of this PR
* splitting high-level generated interface from low-level direct mapping #87
* telemetry for higher-level generated code #88
@nfx nfx linked a pull request Nov 21, 2022 that will close this issue
@nfx nfx closed this as completed in #131 Nov 23, 2022
nfx added a commit that referenced this issue Nov 23, 2022
This PR addresses two major issues
* `mockgen` cannot yet mock higher-level wrappers, like `*AndWait`
because of generics are not yet supported by gomock:
golang/mock#621
* fundamentally fixes #87

# Interoperability with `gomock`

When developing large applications, you find yourself in need of mocking
APIs. For Go, there's [`gomock`](https://github.com/golang/mock)
framework for code generating testing mocks. In this small example,
we'll show how to use `gomock` with Databricks SDK for Go.

Please read through
[`dbfs_test.go`](https://github.com/databricks/databricks-sdk-go/pull/131/files#diff-ac4ba8227927778705ac100663a6f04a314e590b0d0f19c1699fe63ae62b801e)
test example.

## Declaring which mocks to generate

```go
//go:generate go run github.com/golang/mock/mockgen@latest -package=mocks -destination=mocks/dbfs.go github.com/databricks/databricks-sdk-go/service/dbfs DbfsService
```

* `go run github.com/golang/mock/mockgen@latest` downloads and executes
the latest version of `mockgen` command
* `-package=mocks` instructs to generate mocks in the `mocks` package
* `-destination=mocks/dbfs.go` instructs to create `dbfs.go` file with
mock stubs.
* `github.com/databricks/databricks-sdk-go/service/dbfs` tells which
Databricks package to look services in.
* `DbfsService` tells which services to generate mocks for.

## Initializing `gomock`

Every test needs the following preamble:

```go
ctrl := gomock.NewController(t)
defer ctrl.Finish()
```

## Mocking individual methods with `gomock`

Every actual method call must be mocked for the test to pass:

```go
mockDbfs := mocks.NewMockDbfsService(ctrl)
mockDbfs.EXPECT().Create(gomock.Any(), gomock.Eq(dbfs.Create{
    Path:      "/a/b/c",
    Overwrite: true,
})).Return(&dbfs.CreateResponse{
    Handle: 123,
}, nil)
```

## Testing idioms with Databricks SDK for Go

You can stub out the auth with the `databricks.NewMockConfig(nil)`
helper function. Every service has a public property with the name of
the service plus `Service` suffix. You have to manually set the stubs
for every service that is called in unit tests.

```go
w := workspaces.New(databricks.NewMockConfig(nil))
w.Dbfs.DbfsService = mockDbfs
```

## Running this example

1. Run `go mod tidy` in this folder to create `go.sum` file to pick
dependency versions.
2. Run `go mod vendor` to download dependencies into `vendor/`
directory.
3. Run `go generate ./...` to create `mocks/` directory.
4. Run `go test ./...` to invoke tests with mocks.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant