Skip to content

Commit

Permalink
Add Clue Mock Generator tool under mock (#192)
Browse files Browse the repository at this point in the history
* Add Clue Mock Generator under mock

* Handle omitted types correctly in function parameters and results

* Omit repeated types until the last in generated function parameters and results

* Add tests to mock/cmd/cmg/pkg/parse

* Add tests to mock/cmd/cmg/pkg/generate and implement more types

* Add support for generic interfaces

* Support type constraints on named types and finish up some tests

* Omit repeated types in struct literals

* Add Clue Mock Gen usage to example weather system

* Update weather example README with Clue Mock Gen changes
  • Loading branch information
douglaswth committed Feb 20, 2023
1 parent 75a9247 commit 5893311
Show file tree
Hide file tree
Showing 89 changed files with 3,505 additions and 289 deletions.
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Below are some guidelines to follow when contributing to this project:
and follow the checklist presented in the issue description section. A simple
code snippet that reproduces your issue helps immensely.
* If you know how to fix your bug, we highly encourage PR contributions. See
[How Can I Get Started section](#how-can-i-get-started?) on how to submit a PR.
[How Can I Get Started section](#how-can-i-get-started) on how to submit a PR.
* For feature requests and submitting major changes, [open an issue](https://github.com/goadesign/clue/issues/new)
or hop on to our slack channel (see <https://goa.design> to join) to discuss
the feature first.
Expand Down
44 changes: 25 additions & 19 deletions example/weather/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ check := health.Handler(health.NewChecker(

The health check and metric handlers are mounted on a separate HTTP handler (the
global `http` standard library handler) to avoid logging, tracing and otherwise
instrumenting the correspinding requests.
instrumenting the corresponding requests.

```go
http.Handle("/livez", check)
Expand Down Expand Up @@ -246,14 +246,17 @@ func New(cc *grpc.ClientConn) Client {
}
```

The mock is instantiated via the `NewMock` function located in the `mock.go` file:
The mock is instantiated via the `NewClient` function located in the
`mocks/client.go` file that is generated using the `cmg` tool:

```go
var _ Client = &Mock{}

// NewMock returns a new mock client.
func NewMock(t *testing.T) *Mock {
return &Mock{mock.New(), t}
func NewClient(t *testing.T) *Client {
var (
m = &Client{mock.New(), t}
_ = forecaster.Client = m
)
return m
}
```

Expand All @@ -262,43 +265,46 @@ create call sequences and validate them:

```go
type (
// Mock implementation of the forecast client.
Mock struct {
// Mock implementation of the forecast client.
Client struct {
m *mock.Mock
t *testing.T
}

ClientGetForecastFunc func(ctx context.Context, lat, long float64) (*forecaster.Forecast, error)
)
```

```go
// AddGetForecastFunc adds f to the mocked call sequence.
func (m *Mock) AddGetForecastFunc(f GetForecastFunc) {
func (m *Client) AddGetForecast(f ClientGetForecastFunc) {
m.m.Add("GetForecast", f)
}

// SetGetForecastFunc sets f for all calls to the mocked method.
func (m *Mock) SetGetForecastFunc(f GetForecastFunc) {
func (m *Client) SetGetForecast(f ClientGetForecastFunc) {
m.m.Set("GetForecast", f)
}

// GetForecast implements the Client interface.
func (m *Mock) GetForecast(ctx context.Context, lat, long float64) (*Forecast, error) {
func (m *Client) GetForecast(ctx context.Context, lat, long float64) (*forecaster.Forecast, error) {
if f := m.m.Next("GetForecast"); f != nil {
return f.(GetForecastFunc)(ctx, lat, long)
return f.(ClientGetForecastFunc)(ctx, lat, long)
}
m.t.Error("unexpected call to GetForecast")
m.t.Helper()
m.t.Error("unexpected GetForecast call")
return nil, nil
}
```

Tests leverage the `AddGetForecastFunc` and `SetGetForecastFunc` methods to
configure the mock client:
Tests leverage the `AddGetForecast` and `SetGetForecast` methods to configure
the mock client:

```go
lmock := locator.NewMock(t)
lmock.AddGetLocationFunc(c.locationFunc) // Mock the locator service.
fmock := forecaster.NewMock(t)
fmock.AddGetForecastFunc(c.forecastFunc) // Mock the forecast service.
lmock := mocklocator.NewClient(t)
lmock.AddGetLocation(c.locationFunc) // Mock the locator service.
fmock := mockforecaster.NewClient(t)
fmock.AddGetForecast(c.forecastFunc) // Mock the forecast service.
s := New(fmock, lmock) // Create front service instance for testing
```

Expand Down
1 change: 1 addition & 0 deletions example/weather/scripts/gen
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ echo "Generating Goa code..."

for svc in front forecaster locator; do
goa gen goa.design/clue/example/weather/services/${svc}/design -o services/${svc}
cmg gen ./services/${svc}/clients/*/
done

popd
1 change: 1 addition & 0 deletions example/weather/scripts/setup
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ fi

go mod download
go install honnef.co/go/tools/cmd/staticcheck@latest
go install goa.design/clue/mock/cmd/cmg@latest
go install goa.design/model/cmd/mdl@latest
go install goa.design/goa/v3/...@v3
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.27.1
Expand Down
54 changes: 0 additions & 54 deletions example/weather/services/forecaster/clients/weathergov/mock.go

This file was deleted.

126 changes: 126 additions & 0 deletions example/weather/services/forecaster/clients/weathergov/mocks/client.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions example/weather/services/forecaster/forecast_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ import (
"testing"

"goa.design/clue/example/weather/services/forecaster/clients/weathergov"
mockweathergov "goa.design/clue/example/weather/services/forecaster/clients/weathergov/mocks"
genforecaster "goa.design/clue/example/weather/services/forecaster/gen/forecaster"
)

func TestForecast(t *testing.T) {
// Create mock call sequence with first successful call returning a
// forecast then failing.
wc := weathergov.NewMock(t)
wc.AddGetForecastFunc(func(ctx context.Context, lat, long float64) (*weathergov.Forecast, error) {
wc := mockweathergov.NewClient(t)
wc.AddGetForecast(func(ctx context.Context, lat, long float64) (*weathergov.Forecast, error) {
// Make sure service passes the right values to the client
if lat != latitude {
t.Errorf("got latitude %f, expected %f", lat, latitude)
Expand All @@ -23,7 +24,7 @@ func TestForecast(t *testing.T) {
}
return mockForecast, nil
})
wc.AddGetForecastFunc(func(_ context.Context, _, _ float64) (*weathergov.Forecast, error) {
wc.AddGetForecast(func(_ context.Context, _, _ float64) (*weathergov.Forecast, error) {
return nil, fmt.Errorf("test failure")
})

Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Code generated with goa v3.10.2, DO NOT EDIT.
// Code generated with goa v3.11.0, DO NOT EDIT.
//
// Forecaster protocol buffer definition
//
Expand Down
Loading

0 comments on commit 5893311

Please sign in to comment.