Skip to content

Commit ce926c4

Browse files
authored
Add fake package to azcore (#20711)
* Add fake package to azcore This is the supporting infrastructure for the generated SDK fakes. * fix doc comment
1 parent 8e0f66e commit ce926c4

File tree

13 files changed

+1223
-19
lines changed

13 files changed

+1223
-19
lines changed

sdk/azcore/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
* Added field `SpanFromContext` to `tracing.TracerOptions`.
1212
* Added methods `Enabled()`, `SetAttributes()`, and `SpanFromContext()` to `tracing.Tracer`.
1313
* Added supporting pipeline policies to include HTTP spans when creating clients.
14+
* Added package `fake` to support generated fakes packages in SDKs.
15+
* The package contains public surface area exposed by fake servers and supporting APIs intended only for use by the fake server implementations.
16+
* Added an internal fake poller implementation.
1417

1518
### Breaking Changes
1619

sdk/azcore/fake/example_test.go

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
//go:build go1.18
2+
// +build go1.18
3+
4+
// Copyright (c) Microsoft Corporation. All rights reserved.
5+
// Licensed under the MIT License.
6+
7+
package fake_test
8+
9+
import (
10+
"errors"
11+
"net/http"
12+
13+
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
14+
"github.com/Azure/azure-sdk-for-go/sdk/azcore/fake"
15+
)
16+
17+
// Widget is a hypothetical type used in the following examples.
18+
type Widget struct {
19+
ID int
20+
Shape string
21+
}
22+
23+
// WidgetResponse is a hypothetical type used in the following examples.
24+
type WidgetResponse struct {
25+
Widget
26+
}
27+
28+
// WidgetListResponse is a hypothetical type used in the following examples.
29+
type WidgetListResponse struct {
30+
Widgets []Widget
31+
}
32+
33+
func ExampleNewTokenCredential() {
34+
// create a fake azcore.TokenCredential
35+
// the fake is used as the client credential during testing with fakes.
36+
var _ azcore.TokenCredential = fake.NewTokenCredential()
37+
}
38+
39+
func ExampleTokenCredential_SetError() {
40+
cred := fake.NewTokenCredential()
41+
42+
// set an error to be returned during authentication
43+
cred.SetError(errors.New("failed to authenticate"))
44+
}
45+
46+
func ExampleResponder() {
47+
// for a hypothetical API GetNextWidget(context.Context) (WidgetResponse, error)
48+
49+
// a Responder is used to build a scalar response
50+
resp := fake.Responder[WidgetResponse]{}
51+
52+
// here we set the instance of Widget the Responder is to return
53+
resp.Set(WidgetResponse{
54+
Widget{ID: 123, Shape: "triangle"},
55+
})
56+
57+
// optional HTTP headers can also be included in the raw response
58+
resp.SetHeader("custom-header1", "value1")
59+
resp.SetHeader("custom-header2", "value2")
60+
}
61+
62+
func ExampleErrorResponder() {
63+
// an ErrorResponder is used to build an error response
64+
errResp := fake.ErrorResponder{}
65+
66+
// use SetError to return a generic error
67+
errResp.SetError(errors.New("the system is down"))
68+
69+
// to return an *azcore.ResponseError, use SetResponseError
70+
errResp.SetResponseError("ErrorCodeConflict", http.StatusConflict)
71+
72+
// ErrorResponder returns a singular error, so calling Set* APIs overwrites any previous value
73+
}
74+
75+
func ExamplePagerResponder() {
76+
// for a hypothetical API NewListWidgetsPager() *runtime.Pager[WidgetListResponse]
77+
78+
// a PagerResponder is used to build a sequence of responses for a paged operation
79+
pagerResp := fake.PagerResponder[WidgetListResponse]{}
80+
81+
// use AddPage to add one or more pages to the response.
82+
// responses are returned in the order in which they were added.
83+
pagerResp.AddPage(WidgetListResponse{
84+
Widgets: []Widget{
85+
{ID: 1, Shape: "circle"},
86+
{ID: 2, Shape: "square"},
87+
{ID: 3, Shape: "triangle"},
88+
},
89+
}, nil)
90+
pagerResp.AddPage(WidgetListResponse{
91+
Widgets: []Widget{
92+
{ID: 4, Shape: "rectangle"},
93+
{ID: 5, Shape: "rhombus"},
94+
},
95+
}, nil)
96+
97+
// errors can also be included in the sequence of responses.
98+
// this can be used to simulate an error during paging.
99+
pagerResp.AddError(errors.New("network too slow"))
100+
101+
pagerResp.AddPage(WidgetListResponse{
102+
Widgets: []Widget{
103+
{ID: 6, Shape: "trapezoid"},
104+
},
105+
}, nil)
106+
}
107+
108+
func ExamplePollerResponder() {
109+
// for a hypothetical API BeginCreateWidget(context.Context) (*runtime.Poller[WidgetResponse], error)
110+
111+
// a PollerResponder is used to build a sequence of responses for a long-running operation
112+
pollerResp := fake.PollerResponder[WidgetResponse]{}
113+
114+
// use AddNonTerminalResponse to add one or more non-terminal responses
115+
// to the sequence of responses. this is to simulate polling on a LRO.
116+
// non-terminal responses are optional. exclude them to simulate a LRO
117+
// that synchronously completes.
118+
pollerResp.AddNonTerminalResponse(nil)
119+
120+
// non-terminal errors can also be included in the sequence of responses.
121+
// use this to simulate an error during polling.
122+
pollerResp.AddNonTerminalError(errors.New("flaky network"))
123+
124+
// use SetTerminalResponse to successfully terminate the long-running operation.
125+
// the provided value will be returned as the terminal response.
126+
pollerResp.SetTerminalResponse(WidgetResponse{
127+
Widget: Widget{
128+
ID: 987,
129+
Shape: "dodecahedron",
130+
},
131+
})
132+
}
133+
134+
func ExamplePollerResponder_SetTerminalError() {
135+
// for a hypothetical API BeginCreateWidget(context.Context) (*runtime.Poller[WidgetResponse], error)
136+
137+
// a PollerResponder is used to build a sequence of responses for a long-running operation
138+
pollerResp := fake.PollerResponder[WidgetResponse]{}
139+
140+
// use SetTerminalError to terminate the long-running operation with an error.
141+
// this returns an *azcore.ResponseError as the terminal response.
142+
pollerResp.SetTerminalError("NoMoreWidgets", http.StatusBadRequest)
143+
144+
// note that SetTerminalResponse and SetTerminalError are meant to be mutually exclusive.
145+
// in the event that both are called, the result from SetTerminalError will be used.
146+
}

0 commit comments

Comments
 (0)