github.com/Axway/agent-sdk@v1.1.101/pkg/apic/apiserver/clients/api/v1/client_test.go (about) 1 package v1 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "log" 7 "net/http" 8 "net/url" 9 "os" 10 "testing" 11 "time" 12 13 "github.com/Axway/agent-sdk/pkg/apic" 14 v1 "github.com/Axway/agent-sdk/pkg/apic/apiserver/models/api/v1" 15 management "github.com/Axway/agent-sdk/pkg/apic/apiserver/models/management/v1alpha1" 16 "github.com/stretchr/testify/assert" 17 "gopkg.in/h2non/gock.v1" 18 ) 19 20 const privKey = "testdata/privatekey" 21 const pubKey = "testdata/publickey" 22 const uaHeader = "fake-agent" 23 24 const mockJSONEnv = `{ 25 "group": "management", 26 "apiVersion": "v1alpha1", 27 "kind": "Environment", 28 "name": "test-env-1", 29 "title": "test-env-1", 30 "metadata": { 31 "id": "e4f1cf5371cd390b0171cd43d7460056", 32 "audit": { 33 "createTimestamp": "2020-04-30T22:45:07.533+0000", 34 "createUserId": "serviceaccount_1234", 35 "modifyTimestamp": "2020-04-30T22:45:07.533+0000", 36 "modifyUserId": "serviceaccount_1234" 37 }, 38 "resourceVersion": "297", 39 "references": [] 40 }, 41 "attributes": { 42 "attr": "value" 43 }, 44 "tags": ["tag1", "tag2"], 45 "spec": { 46 "description": "desc" 47 } 48 }` 49 50 const mockJSONApiSvc = `{ 51 "group": "management", 52 "apiVersion": "v1alpha1", 53 "kind": "APIService", 54 "name": "test-api-svc", 55 "title": "test-api-svc", 56 "metadata": { 57 "id": "e4e7efa47287250c017296c54e3f01a6", 58 "audit": { 59 "createTimestamp": "2020-06-09T01:50:12.548+0000", 60 "modifyTimestamp": "2020-06-09T01:50:12.548+0000" 61 }, 62 "scope": { 63 "id": "e4e7efa47287250c017296c54dd301a3", 64 "kind": "Environment", 65 "name": "test-env-1" 66 }, 67 "resourceVersion": "696", 68 "references": [] 69 }, 70 "attributes": { 71 "attr": "value" 72 }, 73 "tags": [ 74 "atag" 75 ], 76 "spec": {} 77 }` 78 79 var mockEnv = &v1.ResourceInstance{} 80 var mockEnvUpdated = &v1.ResourceInstance{} 81 var mockAPISvc = &v1.ResourceInstance{} 82 var client = &Client{} 83 84 func createEnv(client Unscoped) (*v1.ResourceInstance, error) { 85 created, err := client.Create(&v1.ResourceInstance{ 86 ResourceMeta: v1.ResourceMeta{ 87 GroupVersionKind: management.EnvironmentGVK(), 88 Name: "test-env-1", 89 Title: "test-env-1", 90 Tags: []string{"atag"}, 91 Attributes: map[string]string{"attr": "value"}, 92 }, 93 Spec: map[string]interface{}{}, 94 }) 95 return created, err 96 } 97 98 func TestMain(m *testing.M) { 99 json.Unmarshal([]byte(mockJSONEnv), mockEnv) 100 json.Unmarshal([]byte(mockJSONEnv), mockEnvUpdated) 101 mockEnvUpdated.Title = "updated-testenv-title" 102 json.Unmarshal([]byte(mockJSONApiSvc), mockAPISvc) 103 104 newClient, err := NewClient( 105 "http://localhost:8080/apis", 106 UserAgent(uaHeader), 107 BasicAuth( 108 "admin", 109 "servicesecret", 110 "admin", 111 "123", 112 ), 113 ).ForKind(management.EnvironmentGVK()) 114 client = newClient.(*Client) 115 if err != nil { 116 log.Fatalf("Error in test setup: %s", err) 117 os.Exit(1) 118 } 119 os.Exit(m.Run()) 120 } 121 122 func TestUnscoped(t *testing.T) { 123 defer gock.Off() 124 // Create env 125 gock.New("http://localhost:8080/apis"). 126 Post("/management/v1alpha1/environments"). 127 MatchHeader("User-Agent", "fake-agent"). 128 Reply(201). 129 JSON(mockEnv) 130 131 gock.New("http://localhost:8080/apis"). 132 Put("/management/v1alpha1/environments/test-env-1"). 133 Reply(200). 134 JSON(mockEnvUpdated) 135 136 gock.New("http://localhost:8080/apis"). 137 Get("/management/v1alpha1/environments/test-env-1"). 138 Reply(200). 139 JSON(mockEnv) 140 141 gock.New("http://localhost:8080/apis"). 142 Get("/management/v1alpha1/environments"). 143 Reply(200). 144 JSON([]*v1.ResourceInstance{mockEnv}) 145 146 gock.New("http://localhost:8080/apis"). 147 Delete("/management/v1alpha1/environments/test-env-1"). 148 Reply(204) 149 150 created, err := createEnv(client) 151 152 if err != nil { 153 t.Fatalf("Failed to create: %s", err) 154 } 155 156 // Get env by name 157 _, err = client.Get(created.Name) 158 if err != nil { 159 t.Fatalf("Failed to get env by name: %s", err) 160 } 161 162 // Update env 163 created.Title = "updated-testenv-title" 164 updatedEnv, err := client.Update(created) 165 166 if updatedEnv.Title != mockEnvUpdated.Title { 167 t.Fatalf("Updated resource name does not match %s. Received %s", mockEnvUpdated.Title, updatedEnv.Title) 168 } 169 170 if err != nil { 171 t.Fatalf("Failed to update: %s", err) 172 } 173 174 // Get all envs 175 envList, err := client.List() 176 if err != nil { 177 t.Fatalf("Failed to list environments: %s", err) 178 } 179 180 found := false 181 for _, env := range envList { 182 if env.Name == created.Name { 183 found = true 184 t.Log("Found in list: ", env) 185 break 186 } 187 } 188 189 if !found { 190 t.Fatalf("Cannot find created environment %v", created) 191 } 192 193 err = client.Delete(created) 194 if err != nil { 195 t.Fatalf("Failed to delete: %s", err) 196 } 197 } 198 199 func TestScoped(t *testing.T) { 200 defer gock.Off() 201 // Create env 202 gock.New("http://localhost:8080/apis"). 203 Post("/management/v1alpha1/environments"). 204 Reply(201). 205 JSON(mockEnv) 206 207 gock.New("http://localhost:8080/apis"). 208 Post("/management/v1alpha1/environments/test-env-1/apiservices"). 209 Reply(201). 210 JSON(mockAPISvc) 211 212 gock.New("http://localhost:8080/apis"). 213 Get("/management/v1alpha1/environments/test-env-1/apiservices"). 214 Reply(200). 215 JSON([]*v1.ResourceInstance{mockAPISvc}) 216 217 gock.New("http://localhost:8080/apis"). 218 Delete("/management/v1alpha1/environments/test-env-1/apiservices/test-api-svc"). 219 Reply(204) 220 221 gock.New("http://localhost:8080/apis"). 222 Delete("/management/v1alpha1/environments/test-env-1"). 223 Reply(204) 224 225 env, err := createEnv(client) 226 227 defer func() { 228 err = client.Delete(env) 229 if err != nil { 230 t.Fatalf("Failed: %s", err) 231 } 232 }() 233 234 svcClient, err := client.ForKind(management.APIServiceGVK()) 235 if err != nil { 236 t.Fatalf("Failed: %s", err) 237 } 238 svcClient = svcClient.WithScope(env.Name).(*Client) 239 240 svc, err := svcClient.Create(&v1.ResourceInstance{ 241 ResourceMeta: v1.ResourceMeta{ 242 Name: "test-api-svc", 243 Tags: []string{"atag"}, 244 Attributes: map[string]string{"attr": "value"}, 245 }, 246 Spec: map[string]interface{}{}, 247 }) 248 if err != nil { 249 t.Fatalf("Failed: %s", err) 250 } 251 252 svcs, err := svcClient.List() 253 if err != nil { 254 t.Fatalf("Failed to list api services: %s", err) 255 } 256 found := false 257 for _, s := range svcs { 258 svcClient.Delete(svc) 259 if s.Name == svc.Name { 260 t.Logf("Found created svc %v", s) 261 262 found = true 263 return 264 } 265 } 266 if !found { 267 t.Fatalf("Cannot find created service %v", svc) 268 } 269 270 err = svcClient.Delete(svc) 271 if err != nil { 272 t.Fatalf("Failed: %s", err) 273 } 274 } 275 276 func TestListWithQuery(t *testing.T) { 277 defer gock.Off() 278 // List envs 279 gock.New("http://localhost:8080/apis"). 280 Get("/management/v1alpha1/environments"). 281 MatchHeader("User-Agent", uaHeader). 282 MatchParam("query", `(tags=="test";attributes.attr==("val"))`).Reply(200). 283 JSON([]*v1.ResourceInstance{mockEnv, mockEnv}) 284 285 _, err := client.List(WithQuery(And(TagsIn("test"), AttrIn("attr", "val")))) 286 if err != nil { 287 t.Fatalf("Error: %s", err) 288 } 289 } 290 291 func Test_listAll(t *testing.T) { 292 // Follow the link headers 293 defer gock.Off() 294 gock.New("http://localhost:8080/apis"). 295 Get("/management/v1alpha1/environments"). 296 Reply(200). 297 AddHeader("Link", "</apis/management/v1alpha1/environments?pageSize=20&query=tags%3D%3D%22test%22&page=2>; rel=\"next\", </apis/management/v1alpha1/environments?pageSize=20&query=tags%3D%3D%22test%22&page=1>; rel=\"self\", </apis/management/v1alpha1/environments?pageSize=20&query=tags%3D%3D%22test%22&page=1>; rel=\"first\", </apis/management/v1alpha1/environments?pageSize=20&query=tags%3D%3D%22test%22&page=4>; rel=\"last\""). 298 JSON([]*v1.ResourceInstance{mockEnv}) 299 300 gock.New("http://localhost:8080/apis"). 301 Get("/management/v1alpha1/environments"). 302 Reply(200). 303 AddHeader("Link", "</apis/management/v1alpha1/environments?pageSize=20&query=tags%3D%3D%22test%22&page=1>; rel=\"self\", </apis/management/v1alpha1/environments?pageSize=20&query=tags%3D%3D%22test%22&page=1>; rel=\"first\", </apis/management/v1alpha1/environments?pageSize=20&query=tags%3D%3D%22test%22&page=4>; rel=\"last\""). 304 JSON([]*v1.ResourceInstance{mockEnv}) 305 306 items, err := client.List(WithQuery(TagsIn("test"))) 307 if err != nil { 308 t.Fatalf("Error: %s", err) 309 } 310 assert.Equal(t, 2, len(items)) 311 312 // handle an error from the client 313 gock.New("http://localhost:8080/apis"). 314 Get("/management/v1alpha1/environments"). 315 Reply(500). 316 SetError(&url.Error{}) 317 318 _, err = client.List() 319 assert.NotNil(t, err) 320 321 // handle a successful response, but a 500 error 322 gock.New("http://localhost:8080/apis"). 323 Get("/management/v1alpha1/environments"). 324 Reply(500) 325 326 _, err = client.List() 327 assert.NotNil(t, err) 328 329 // handle a successful request, then a failed request 330 gock.New("http://localhost:8080/apis"). 331 Get("/management/v1alpha1/environments"). 332 Reply(200). 333 AddHeader("Link", "</apis/management/v1alpha1/environments?pageSize=20&query=tags%3D%3D%22test%22&page=2>; rel=\"next\", </apis/management/v1alpha1/environments?pageSize=20&query=tags%3D%3D%22test%22&page=1>; rel=\"self\", </apis/management/v1alpha1/environments?pageSize=20&query=tags%3D%3D%22test%22&page=1>; rel=\"first\", </apis/management/v1alpha1/environments?pageSize=20&query=tags%3D%3D%22test%22&page=4>; rel=\"last\""). 334 JSON([]*v1.ResourceInstance{mockEnv}) 335 336 gock.New("http://localhost:8080/apis"). 337 Get("/management/v1alpha1/environments"). 338 Reply(500). 339 AddHeader("Link", "</apis/management/v1alpha1/environments?pageSize=20&query=tags%3D%3D%22test%22&page=1>; rel=\"self\", </apis/management/v1alpha1/environments?pageSize=20&query=tags%3D%3D%22test%22&page=1>; rel=\"first\", </apis/management/v1alpha1/environments?pageSize=20&query=tags%3D%3D%22test%22&page=4>; rel=\"last\""). 340 JSON([]*v1.ResourceInstance{}) 341 342 items, err = client.List() 343 assert.Equal(t, 0, len(items)) 344 assert.NotNil(t, err) 345 } 346 347 func TestJWTAuth(t *testing.T) { 348 tenantId := "1234" 349 c := NewClient("http://localhost:8080", 350 JWTAuth( 351 tenantId, 352 privKey, 353 pubKey, 354 "", 355 "http://localhost:8080/auth/realms/Broker/protocol/openid-connect/token", 356 "http://localhost:8080/auth/realms/Broker", 357 "serviceaccount_1234", 358 10*time.Second, 359 ), 360 UserAgent(uaHeader), 361 ) 362 363 assert.Equal(t, uaHeader, c.userAgent) 364 365 jAuthStruct, ok := c.auth.(*jwtAuth) 366 367 assert.True(t, ok) 368 jAuthStruct.tokenGetter = apic.MockTokenGetter 369 370 req := &http.Request{ 371 Header: make(http.Header), 372 } 373 err := c.intercept(req) 374 assert.Nil(t, err) 375 376 userAgent := req.Header.Get("User-Agent") 377 assert.Equal(t, uaHeader, userAgent) 378 379 authorization := req.Header.Get("Authorization") 380 assert.NotEmpty(t, authorization) 381 382 tenant := req.Header.Get("X-Axway-Tenant-Id") 383 assert.Equal(t, tenantId, tenant) 384 385 instance := req.Header.Get("X-Axway-Instance-Id") 386 assert.Equal(t, "", instance) 387 } 388 389 func TestResponseErrors(t *testing.T) { 390 tests := []struct { 391 status int 392 err error 393 }{ 394 {status: 400, err: BadRequestError{}}, 395 {status: 401, err: UnauthorizedError{}}, 396 {status: 403, err: ForbiddenError{}}, 397 {status: 404, err: NotFoundError{}}, 398 {status: 409, err: ConflictError{}}, 399 {status: 500, err: InternalServerError{}}, 400 {status: 600, err: UnexpectedError{}}, 401 } 402 403 for i := range tests { 404 tc := tests[i] 405 t.Run(fmt.Sprintf("%d error", tc.status), func(t *testing.T) { 406 defer gock.Off() 407 gock.New("http://localhost:8080/apis"). 408 Get("/management/v1alpha1/environments"). 409 Reply(tc.status). 410 JSON(mockEnv) 411 412 _, err := client.List() 413 414 switch tc.status { 415 case 400: 416 errType, ok := err.(BadRequestError) 417 assert.True(t, ok) 418 assert.NotEmpty(t, errType.Error()) 419 assert.IsType(t, BadRequestError{}, errType) 420 case 401: 421 errType, ok := err.(UnauthorizedError) 422 assert.True(t, ok) 423 assert.NotEmpty(t, errType.Error()) 424 assert.IsType(t, UnauthorizedError{}, errType) 425 case 403: 426 errType, ok := err.(ForbiddenError) 427 assert.True(t, ok) 428 assert.NotEmpty(t, errType.Error()) 429 assert.IsType(t, ForbiddenError{}, errType) 430 case 404: 431 errType, ok := err.(NotFoundError) 432 assert.True(t, ok) 433 assert.NotEmpty(t, errType.Error()) 434 assert.IsType(t, NotFoundError{}, errType) 435 case 409: 436 errType, ok := err.(ConflictError) 437 assert.True(t, ok) 438 assert.NotEmpty(t, errType.Error()) 439 assert.IsType(t, ConflictError{}, errType) 440 case 500: 441 errType, ok := err.(InternalServerError) 442 assert.True(t, ok) 443 assert.NotEmpty(t, errType.Error()) 444 assert.IsType(t, InternalServerError{}, errType) 445 default: 446 errType, ok := err.(UnexpectedError) 447 assert.True(t, ok) 448 assert.NotEmpty(t, errType.Error()) 449 assert.IsType(t, UnexpectedError{}, errType) 450 } 451 452 }) 453 } 454 } 455 456 func TestGetError(t *testing.T) { 457 defer gock.Off() 458 gock.New("http://localhost:8080/apis"). 459 Get("/management/v1alpha1/environments"). 460 Reply(500). 461 JSON(mockEnv) 462 463 _, err := client.Get("name") 464 465 if err == nil { 466 t.Fatalf("Expected Update to fail: %s", err) 467 } 468 } 469 470 func TestDeleteError(t *testing.T) { 471 defer gock.Off() 472 gock.New("http://localhost:8080/apis"). 473 Delete("/management/v1alpha1/environments"). 474 Reply(500). 475 JSON(mockEnv) 476 477 err := client.Delete(&v1.ResourceInstance{ 478 ResourceMeta: v1.ResourceMeta{ 479 GroupVersionKind: management.EnvironmentGVK(), 480 Name: "test-env-1", 481 Title: "test-env-1", 482 Tags: []string{"atag"}, 483 Attributes: map[string]string{"attr": "value"}, 484 }, 485 Spec: map[string]interface{}{}, 486 }) 487 488 if err == nil { 489 t.Fatalf("Expected delete to fail: %s", err) 490 } 491 } 492 493 func TestCreateError(t *testing.T) { 494 defer gock.Off() 495 gock.New("http://localhost:8080/apis"). 496 Post("/management/v1alpha1/environments"). 497 Reply(500). 498 JSON(mockEnv) 499 500 _, err := createEnv(client) 501 502 if err == nil { 503 t.Fatalf("Expected create to fail: %s", err) 504 } 505 } 506 507 func TestUpdateError(t *testing.T) { 508 defer gock.Off() 509 gock.New("http://localhost:8080/apis"). 510 Put("/management/v1alpha1/environments"). 511 Reply(500). 512 JSON(mockEnv) 513 514 _, err := client.Update(&v1.ResourceInstance{ 515 ResourceMeta: v1.ResourceMeta{ 516 GroupVersionKind: management.EnvironmentGVK(), 517 Name: "test-env-1", 518 Title: "test-env-1", 519 Tags: []string{"atag"}, 520 Attributes: map[string]string{"attr": "value"}, 521 }, 522 Spec: map[string]interface{}{}, 523 }) 524 525 if err == nil { 526 t.Fatalf("Expected update to fail: %s", err) 527 } 528 } 529 530 func TestHTTPClient(t *testing.T) { 531 newClient := &http.Client{} 532 533 client := NewClient( 534 "http://localhost:8080/apis", 535 BasicAuth( 536 "admin", 537 "servicesecret", 538 "admin", 539 "123", 540 ), 541 HTTPClient(newClient), 542 ) 543 544 assert.Empty(t, client.userAgent) 545 546 if newClient != client.client { 547 t.Fatalf("Error: expected client.client to be %v but received %v", newClient, client.client) 548 } 549 } 550 551 func TestUpdateMerge(t *testing.T) { 552 oldAPISvc := &management.APIService{ 553 ResourceMeta: v1.ResourceMeta{ 554 GroupVersionKind: v1.GroupVersionKind{}, 555 Name: "name", 556 Metadata: v1.Metadata{ 557 Scope: v1.MetadataScope{ 558 Name: "myenv", 559 }, 560 References: []v1.Reference{}, 561 }, 562 Tags: []string{"old"}, 563 }, 564 } 565 566 newAPISvc := &management.APIService{ 567 ResourceMeta: v1.ResourceMeta{ 568 GroupVersionKind: v1.GroupVersionKind{ 569 GroupKind: v1.GroupKind{ 570 Group: "management", 571 Kind: "APIService", 572 }, 573 APIVersion: "v1alpha1", 574 }, 575 Name: "name", 576 Metadata: v1.Metadata{ 577 Scope: v1.MetadataScope{ 578 Name: "myenv", 579 }, 580 }, 581 Tags: []string{"new"}, 582 }, 583 } 584 585 thisBytes, _ := json.Marshal(newAPISvc) 586 t.Log(string(thisBytes)) 587 588 mergedTags := &management.APIService{ 589 ResourceMeta: v1.ResourceMeta{ 590 GroupVersionKind: v1.GroupVersionKind{}, 591 Name: "name", 592 Metadata: v1.Metadata{ 593 Scope: v1.MetadataScope{ 594 Name: "myenv", 595 }, 596 References: []v1.Reference{}, 597 }, 598 Tags: []string{"old", "new"}, 599 }, 600 } 601 602 mergeError := fmt.Errorf("merge errror") 603 604 getError := InternalServerError{ 605 Errors: []v1.Error{{Status: 500, Detail: "Unkown error"}}, 606 } 607 608 testCases := []struct { 609 name string 610 replyFunc func(*gock.Response) error 611 getStatus int 612 otherStatus int 613 getResponse interface{} 614 newResource v1.Interface 615 mf MergeFunc 616 expectedErr error 617 expectedResource interface{} 618 }{ 619 { 620 name: "it's a create", 621 getResponse: oldAPISvc, 622 newResource: newAPISvc, 623 getStatus: 404, 624 otherStatus: 201, 625 mf: func(fetched v1.Interface, new v1.Interface) (v1.Interface, error) { 626 return new, nil 627 }, 628 expectedErr: nil, 629 expectedResource: newAPISvc, 630 }, 631 { 632 name: "overwriting update", 633 getResponse: oldAPISvc, 634 newResource: newAPISvc, 635 getStatus: 200, 636 otherStatus: 200, 637 mf: func(fetched v1.Interface, new v1.Interface) (v1.Interface, error) { 638 return new, nil 639 }, 640 expectedErr: nil, 641 expectedResource: newAPISvc, 642 }, 643 { 644 name: "merging tags update", 645 getResponse: oldAPISvc, 646 newResource: newAPISvc, 647 getStatus: 200, 648 otherStatus: 200, 649 mf: func(fetched v1.Interface, new v1.Interface) (v1.Interface, error) { 650 f, err := fetched.AsInstance() 651 if err != nil { 652 return nil, err 653 } 654 655 f.SetTags(append(f.GetTags(), new.GetTags()...)) 656 657 return f, nil 658 }, 659 expectedErr: nil, 660 expectedResource: mergedTags, 661 }, 662 { 663 name: "merge error", 664 getResponse: oldAPISvc, 665 newResource: newAPISvc, 666 getStatus: 200, 667 otherStatus: 200, 668 mf: func(fetched v1.Interface, new v1.Interface) (v1.Interface, error) { 669 return nil, mergeError 670 }, 671 expectedErr: mergeError, 672 expectedResource: nil, 673 }, 674 { 675 name: "get error", 676 getResponse: v1.ErrorResponse{Errors: getError.Errors}, 677 newResource: newAPISvc, 678 getStatus: 500, 679 otherStatus: 200, 680 mf: func(fetched v1.Interface, new v1.Interface) (v1.Interface, error) { 681 return nil, mergeError 682 }, 683 expectedErr: getError, 684 expectedResource: nil, 685 }} 686 logger := WithLogger(noOpLogger{}) 687 c, err := NewClient("http://localhost:8080/apis", logger).ForKind(management.APIServiceGVK()) 688 689 if err != nil { 690 t.Fatalf("Failed due: %s ", err) 691 } 692 for i := range testCases { 693 tc := testCases[i] 694 t.Run(tc.name, func(t *testing.T) { 695 defer gock.Off() 696 gock.Observe(gock.DumpRequest) 697 698 gock.New("http://localhost:8080/apis"). 699 Get("/management/v1alpha1/environments/myenv/apiservices/name"). 700 Reply(tc.getStatus). 701 JSON(tc.getResponse) 702 703 switch { 704 case tc.expectedErr == mergeError: 705 case tc.getStatus == 404: 706 gock.New("http://localhost:8080/apis"). 707 Post("/management/v1alpha1/environments/myenv/apiservices"). 708 JSON(tc.expectedResource). 709 Reply(tc.otherStatus). 710 JSON(tc.expectedResource) 711 case tc.getStatus == 200: 712 gock.New("http://localhost:8080/apis"). 713 Put("/management/v1alpha1/environments/myenv/apiservices/name"). 714 JSON(tc.expectedResource). 715 Reply(tc.otherStatus). 716 JSON(tc.expectedResource) 717 } 718 719 newRI, err := tc.newResource.AsInstance() 720 if err != nil { 721 t.Fatal(err) 722 } 723 724 _, err = c.Update(newRI, Merge(tc.mf)) 725 726 switch { 727 case err == nil && tc.expectedErr == nil: 728 case err != nil && tc.expectedErr == nil: 729 t.Error("Not expecting error, got: ", err) 730 case err == nil && tc.expectedErr != nil: 731 t.Error("Expected error: ", tc.expectedErr, "; got no error") 732 case err.Error() != tc.expectedErr.Error(): 733 t.Error("Expected error: ", tc.expectedErr, "; got: ", err) 734 } 735 736 if gock.HasUnmatchedRequest() { 737 t.Errorf("Expected more requests: %+v", gock.GetUnmatchedRequests()) 738 } 739 }) 740 } 741 }