@@ -9,182 +9,159 @@ import 'package:test/test.dart';
9
9
10
10
import '../mocks/mock_hub.dart' ;
11
11
12
+ final requestUri = Uri .parse ('https://example.com' );
13
+
12
14
void main () {
13
15
group (SentryHttpClient , () {
14
- test ('GET: happy path' , () async {
15
- final mockHub = MockHub ();
16
+ late var fixture;
16
17
17
- final mockClient = MockClient ((request) async {
18
- expect (request.url, Uri .parse ('https://example.com' ));
19
- return Response ('' , 200 , reasonPhrase: 'OK' );
20
- });
18
+ setUp (() {
19
+ fixture = Fixture ();
20
+ });
21
21
22
- final client = SentryHttpClient (client: mockClient, hub: mockHub);
22
+ test ('GET: happy path' , () async {
23
+ final sut =
24
+ fixture.getSut (fixture.getClient (statusCode: 200 , reason: 'OK' ));
23
25
24
- final response = await client .get (Uri . parse ( 'https://example.com' ) );
26
+ final response = await sut .get (requestUri );
25
27
expect (response.statusCode, 200 );
26
28
27
- expect (mockHub .addBreadcrumbCalls.length, 1 );
28
- final breadcrumb = mockHub .addBreadcrumbCalls.first.crumb;
29
+ expect (fixture.hub .addBreadcrumbCalls.length, 1 );
30
+ final breadcrumb = fixture.hub .addBreadcrumbCalls.first.crumb;
29
31
30
32
expect (breadcrumb.type, 'http' );
31
- expect (breadcrumb.data, < String , dynamic > {
32
- 'url' : 'https://example.com' ,
33
- 'method' : 'GET' ,
34
- 'status_code' : 200 ,
35
- 'reason' : 'OK' ,
36
- });
33
+ expect (breadcrumb.data? ['url' ], 'https://example.com' );
34
+ expect (breadcrumb.data? ['method' ], 'GET' );
35
+ expect (breadcrumb.data? ['status_code' ], 200 );
36
+ expect (breadcrumb.data? ['reason' ], 'OK' );
37
+ expect (breadcrumb.data? ['duration' ], isNotNull);
37
38
});
38
39
39
40
test ('GET: happy path for 404' , () async {
40
- final mockHub = MockHub ();
41
+ final sut = fixture
42
+ .getSut (fixture.getClient (statusCode: 404 , reason: 'NOT FOUND' ));
41
43
42
- final mockClient = MockClient ((request) async {
43
- expect (request.url, Uri .parse ('https://example.com' ));
44
- return Response ('' , 404 , reasonPhrase: 'NOT FOUND' );
45
- });
44
+ final response = await sut.get (requestUri);
46
45
47
- final client = SentryHttpClient (client: mockClient, hub: mockHub);
48
-
49
- final response = await client.get (Uri .parse ('https://example.com' ));
50
46
expect (response.statusCode, 404 );
51
47
52
- expect (mockHub .addBreadcrumbCalls.length, 1 );
53
- final breadcrumb = mockHub .addBreadcrumbCalls.first.crumb;
48
+ expect (fixture.hub .addBreadcrumbCalls.length, 1 );
49
+ final breadcrumb = fixture.hub .addBreadcrumbCalls.first.crumb;
54
50
55
51
expect (breadcrumb.type, 'http' );
56
- expect (breadcrumb.data, < String , dynamic > {
57
- 'url' : 'https://example.com' ,
58
- 'method' : 'GET' ,
59
- 'status_code' : 404 ,
60
- 'reason' : 'NOT FOUND' ,
61
- });
52
+ expect (breadcrumb.data? ['url' ], 'https://example.com' );
53
+ expect (breadcrumb.data? ['method' ], 'GET' );
54
+ expect (breadcrumb.data? ['status_code' ], 404 );
55
+ expect (breadcrumb.data? ['reason' ], 'NOT FOUND' );
56
+ expect (breadcrumb.data? ['duration' ], isNotNull);
62
57
});
63
58
64
59
test ('POST: happy path' , () async {
65
- final mockHub = MockHub ();
66
-
67
- final mockClient = MockClient ((request) async {
68
- expect (request.url, Uri .parse ('https://example.com' ));
69
- return Response ('' , 200 );
70
- });
60
+ final sut = fixture.getSut (fixture.getClient (statusCode: 200 ));
71
61
72
- final client = SentryHttpClient (client: mockClient, hub: mockHub);
73
-
74
- final response = await client.post (Uri .parse ('https://example.com' ));
62
+ final response = await sut.post (requestUri);
75
63
expect (response.statusCode, 200 );
76
64
77
- expect (mockHub .addBreadcrumbCalls.length, 1 );
78
- final breadcrumb = mockHub .addBreadcrumbCalls.first.crumb;
65
+ expect (fixture.hub .addBreadcrumbCalls.length, 1 );
66
+ final breadcrumb = fixture.hub .addBreadcrumbCalls.first.crumb;
79
67
80
68
expect (breadcrumb.type, 'http' );
81
- expect (breadcrumb.data, < String , dynamic > {
82
- 'url' : 'https://example.com' ,
83
- 'method' : 'POST' ,
84
- 'status_code' : 200 ,
85
- });
69
+ expect (breadcrumb.data? ['url' ], 'https://example.com' );
70
+ expect (breadcrumb.data? ['method' ], 'POST' );
71
+ expect (breadcrumb.data? ['status_code' ], 200 );
72
+ expect (breadcrumb.data? ['duration' ], isNotNull);
86
73
});
87
74
88
75
test ('PUT: happy path' , () async {
89
- final mockHub = MockHub ( );
76
+ final sut = fixture. getSut (fixture. getClient (statusCode : 200 ) );
90
77
91
- final mockClient = MockClient ((request) async {
92
- expect (request.url, Uri .parse ('https://example.com' ));
93
- return Response ('' , 200 );
94
- });
95
-
96
- final client = SentryHttpClient (client: mockClient, hub: mockHub);
97
-
98
- final response = await client.put (Uri .parse ('https://example.com' ));
78
+ final response = await sut.put (requestUri);
99
79
expect (response.statusCode, 200 );
100
80
101
- expect (mockHub .addBreadcrumbCalls.length, 1 );
102
- final breadcrumb = mockHub .addBreadcrumbCalls.first.crumb;
81
+ expect (fixture.hub .addBreadcrumbCalls.length, 1 );
82
+ final breadcrumb = fixture.hub .addBreadcrumbCalls.first.crumb;
103
83
104
84
expect (breadcrumb.type, 'http' );
105
- expect (breadcrumb.data, < String , dynamic > {
106
- 'url' : 'https://example.com' ,
107
- 'method' : 'PUT' ,
108
- 'status_code' : 200 ,
109
- });
85
+ expect (breadcrumb.data? ['url' ], 'https://example.com' );
86
+ expect (breadcrumb.data? ['method' ], 'PUT' );
87
+ expect (breadcrumb.data? ['status_code' ], 200 );
88
+ expect (breadcrumb.data? ['duration' ], isNotNull);
110
89
});
111
90
112
91
test ('DELETE: happy path' , () async {
113
- final mockHub = MockHub ();
114
-
115
- final mockClient = MockClient ((request) async {
116
- expect (request.url, Uri .parse ('https://example.com' ));
117
- return Response ('' , 200 , reasonPhrase: 'OK' );
118
- });
119
-
120
- final client = SentryHttpClient (client: mockClient, hub: mockHub);
92
+ final sut = fixture.getSut (fixture.getClient (statusCode: 200 ));
121
93
122
- final response = await client .delete (Uri . parse ( 'https://example.com' ) );
94
+ final response = await sut .delete (requestUri );
123
95
expect (response.statusCode, 200 );
124
96
125
- expect (mockHub .addBreadcrumbCalls.length, 1 );
126
- final breadcrumb = mockHub .addBreadcrumbCalls.first.crumb;
97
+ expect (fixture.hub .addBreadcrumbCalls.length, 1 );
98
+ final breadcrumb = fixture.hub .addBreadcrumbCalls.first.crumb;
127
99
128
100
expect (breadcrumb.type, 'http' );
129
- expect (breadcrumb.data, < String , dynamic > {
130
- 'url' : 'https://example.com' ,
131
- 'method' : 'DELETE' ,
132
- 'status_code' : 200 ,
133
- 'reason' : 'OK' ,
134
- });
101
+ expect (breadcrumb.data? ['url' ], 'https://example.com' );
102
+ expect (breadcrumb.data? ['method' ], 'DELETE' );
103
+ expect (breadcrumb.data? ['status_code' ], 200 );
104
+ expect (breadcrumb.data? ['duration' ], isNotNull);
135
105
});
136
106
137
107
/// Tests, that in case an exception gets thrown, that
138
- /// - no breadcrumb gets added
139
- /// - no exception gets reported by Sentry, in case the user wants to
140
- /// handle the exception
141
- test ('no breadcrumb for ClientException' , () async {
142
- final url = Uri .parse ('https://example.com' );
143
-
144
- final mockHub = MockHub ();
145
-
146
- final mockClient = MockClient ((request) async {
147
- expect (request.url, url);
148
- throw ClientException ('test' , url);
149
- });
150
-
151
- final client = SentryHttpClient (client: mockClient, hub: mockHub);
108
+ /// no exception gets reported by Sentry, in case the user wants to
109
+ /// handle the exception
110
+ test ('no captureException for ClientException' , () async {
111
+ final sut = fixture.getSut (MockClient ((request) async {
112
+ expect (request.url, requestUri);
113
+ throw ClientException ('test' , requestUri);
114
+ }));
152
115
153
116
try {
154
- await client .get (Uri . parse ( 'https://example.com' ) );
117
+ await sut .get (requestUri );
155
118
fail ('Method did not throw' );
156
119
} on ClientException catch (e) {
157
120
expect (e.message, 'test' );
158
- expect (e.uri, url );
121
+ expect (e.uri, requestUri );
159
122
}
160
123
161
- expect (mockHub.addBreadcrumbCalls.length, 0 );
162
- expect (mockHub.captureExceptionCalls.length, 0 );
124
+ expect (fixture.hub.captureExceptionCalls.length, 0 );
163
125
});
164
126
165
127
/// SocketException are only a thing on dart:io platforms.
166
128
/// otherwise this is equal to the test above
167
- test ('no breadcrumb for SocketException' , () async {
168
- final url = Uri .parse ('https://example.com' );
169
-
170
- final mockHub = MockHub ();
171
-
172
- final mockClient = MockClient ((request) async {
173
- expect (request.url, url);
129
+ test ('no captureException for SocketException' , () async {
130
+ final sut = fixture.getSut (MockClient ((request) async {
131
+ expect (request.url, requestUri);
174
132
throw SocketException ('test' );
175
- });
176
-
177
- final client = SentryHttpClient (client: mockClient, hub: mockHub);
133
+ }));
178
134
179
135
try {
180
- await client .get (Uri . parse ( 'https://example.com' ) );
136
+ await sut .get (requestUri );
181
137
fail ('Method did not throw' );
182
138
} on SocketException catch (e) {
183
139
expect (e.message, 'test' );
184
140
}
185
141
186
- expect (mockHub.addBreadcrumbCalls.length, 0 );
187
- expect (mockHub.captureExceptionCalls.length, 0 );
142
+ expect (fixture.hub.captureExceptionCalls.length, 0 );
143
+ });
144
+
145
+ test ('breadcrumb gets added when an exception gets thrown' , () async {
146
+ final sut = fixture.getSut (MockClient ((request) async {
147
+ expect (request.url, requestUri);
148
+ throw Exception ('foo bar' );
149
+ }));
150
+
151
+ try {
152
+ await sut.get (requestUri);
153
+ fail ('Method did not throw' );
154
+ } on Exception catch (_) {}
155
+
156
+ expect (fixture.hub.addBreadcrumbCalls.length, 1 );
157
+
158
+ final breadcrumb = fixture.hub.addBreadcrumbCalls.first.crumb;
159
+
160
+ expect (breadcrumb.type, 'http' );
161
+ expect (breadcrumb.data? ['url' ], 'https://example.com' );
162
+ expect (breadcrumb.data? ['method' ], 'GET' );
163
+ expect (breadcrumb.level, SentryLevel .error);
164
+ expect (breadcrumb.data? ['duration' ], isNotNull);
188
165
});
189
166
190
167
test ('close does get called for user defined client' , () async {
@@ -199,7 +176,41 @@ void main() {
199
176
expect (mockHub.captureExceptionCalls.length, 0 );
200
177
verify (mockClient.close ());
201
178
});
179
+
180
+ test ('Breadcrumb has correct duration' , () async {
181
+ final sut = fixture.getSut (MockClient ((request) async {
182
+ expect (request.url, requestUri);
183
+ await Future .delayed (Duration (seconds: 1 ));
184
+ return Response ('' , 200 , reasonPhrase: 'OK' );
185
+ }));
186
+
187
+ final response = await sut.get (requestUri);
188
+ expect (response.statusCode, 200 );
189
+
190
+ expect (fixture.hub.addBreadcrumbCalls.length, 1 );
191
+ final breadcrumb = fixture.hub.addBreadcrumbCalls.first.crumb;
192
+
193
+ var durationString = breadcrumb.data! ['duration' ]! as String ;
194
+ // we don't check for anything below a second
195
+ expect (durationString.startsWith ('0:00:01' ), true );
196
+ });
202
197
});
203
198
}
204
199
205
200
class CloseableMockClient extends Mock implements BaseClient {}
201
+
202
+ class Fixture {
203
+ SentryHttpClient getSut ([MockClient ? client]) {
204
+ final mc = client ?? getClient ();
205
+ return SentryHttpClient (client: mc, hub: hub);
206
+ }
207
+
208
+ late MockHub hub = MockHub ();
209
+
210
+ MockClient getClient ({int statusCode = 200 , String ? reason}) {
211
+ return MockClient ((request) async {
212
+ expect (request.url, requestUri);
213
+ return Response ('' , statusCode, reasonPhrase: reason);
214
+ });
215
+ }
216
+ }
0 commit comments