github.com/moitias/moq@v0.0.0-20240223074357-5eb0f0ba4054/pkg/moq/moq_test.go (about) 1 package moq 2 3 import ( 4 "bytes" 5 "flag" 6 "fmt" 7 "io" 8 "io/ioutil" 9 "os" 10 "os/exec" 11 "path/filepath" 12 "strings" 13 "testing" 14 15 "github.com/pmezard/go-difflib/difflib" 16 ) 17 18 var update = flag.Bool("update", false, "Update golden files.") 19 20 func TestMoq(t *testing.T) { 21 m, err := New(Config{SrcDir: "testpackages/example"}) 22 if err != nil { 23 t.Fatalf("moq.New: %s", err) 24 } 25 var buf bytes.Buffer 26 err = m.Mock(&buf, "PersonStore") 27 if err != nil { 28 t.Errorf("m.Mock: %s", err) 29 } 30 s := buf.String() 31 // assertions of things that should be mentioned 32 strs := []string{ 33 "package example", 34 "type PersonStoreMock struct", 35 "CreateFunc func(ctx context.Context, person *Person, confirm bool) error", 36 "GetFunc func(ctx context.Context, id string) (*Person, error)", 37 "func (mock *PersonStoreMock) Create(ctx context.Context, person *Person, confirm bool) error", 38 "func (mock *PersonStoreMock) Get(ctx context.Context, id string) (*Person, error)", 39 "panic(\"PersonStoreMock.CreateFunc: method is nil but PersonStore.Create was just called\")", 40 "panic(\"PersonStoreMock.GetFunc: method is nil but PersonStore.Get was just called\")", 41 "mock.lockGet.Lock()", 42 "mock.calls.Get = append(mock.calls.Get, callInfo)", 43 "mock.lockGet.Unlock()", 44 "// ID is the id argument value", 45 } 46 for _, str := range strs { 47 if !strings.Contains(s, str) { 48 t.Errorf("expected but missing: \"%s\"", str) 49 } 50 } 51 } 52 53 func TestMoqWithStaticCheck(t *testing.T) { 54 m, err := New(Config{SrcDir: "testpackages/example"}) 55 if err != nil { 56 t.Fatalf("moq.New: %s", err) 57 } 58 var buf bytes.Buffer 59 err = m.Mock(&buf, "PersonStore") 60 if err != nil { 61 t.Errorf("m.Mock: %s", err) 62 } 63 s := buf.String() 64 // assertions of things that should be mentioned 65 strs := []string{ 66 "package example", 67 "var _ PersonStore = &PersonStoreMock{}", 68 "type PersonStoreMock struct", 69 "CreateFunc func(ctx context.Context, person *Person, confirm bool) error", 70 "GetFunc func(ctx context.Context, id string) (*Person, error)", 71 "func (mock *PersonStoreMock) Create(ctx context.Context, person *Person, confirm bool) error", 72 "func (mock *PersonStoreMock) Get(ctx context.Context, id string) (*Person, error)", 73 "panic(\"PersonStoreMock.CreateFunc: method is nil but PersonStore.Create was just called\")", 74 "panic(\"PersonStoreMock.GetFunc: method is nil but PersonStore.Get was just called\")", 75 "mock.lockGet.Lock()", 76 "mock.calls.Get = append(mock.calls.Get, callInfo)", 77 "mock.lockGet.Unlock()", 78 "// ID is the id argument value", 79 } 80 for _, str := range strs { 81 if !strings.Contains(s, str) { 82 t.Errorf("expected but missing: \"%s\"", str) 83 } 84 } 85 } 86 87 func TestMoqWithAlias(t *testing.T) { 88 m, err := New(Config{SrcDir: "testpackages/example"}) 89 if err != nil { 90 t.Fatalf("moq.New: %s", err) 91 } 92 var buf bytes.Buffer 93 err = m.Mock(&buf, "PersonStore:AnotherPersonStoreMock") 94 if err != nil { 95 t.Errorf("m.Mock: %s", err) 96 } 97 s := buf.String() 98 // assertions of things that should be mentioned 99 strs := []string{ 100 "package example", 101 "type AnotherPersonStoreMock struct", 102 "CreateFunc func(ctx context.Context, person *Person, confirm bool) error", 103 "GetFunc func(ctx context.Context, id string) (*Person, error)", 104 "func (mock *AnotherPersonStoreMock) Create(ctx context.Context, person *Person, confirm bool) error", 105 "func (mock *AnotherPersonStoreMock) Get(ctx context.Context, id string) (*Person, error)", 106 "panic(\"AnotherPersonStoreMock.CreateFunc: method is nil but PersonStore.Create was just called\")", 107 "panic(\"AnotherPersonStoreMock.GetFunc: method is nil but PersonStore.Get was just called\")", 108 "mock.lockGet.Lock()", 109 "mock.calls.Get = append(mock.calls.Get, callInfo)", 110 "mock.lockGet.Unlock()", 111 "// ID is the id argument value", 112 } 113 for _, str := range strs { 114 if !strings.Contains(s, str) { 115 t.Errorf("expected but missing: \"%s\"", str) 116 } 117 } 118 } 119 120 func TestMoqExplicitPackage(t *testing.T) { 121 m, err := New(Config{SrcDir: "testpackages/example", PkgName: "different"}) 122 if err != nil { 123 t.Fatalf("moq.New: %s", err) 124 } 125 var buf bytes.Buffer 126 err = m.Mock(&buf, "PersonStore") 127 if err != nil { 128 t.Errorf("m.Mock: %s", err) 129 } 130 s := buf.String() 131 // assertions of things that should be mentioned 132 strs := []string{ 133 "package different", 134 "type PersonStoreMock struct", 135 "CreateFunc func(ctx context.Context, person *example.Person, confirm bool) error", 136 "GetFunc func(ctx context.Context, id string) (*example.Person, error)", 137 "func (mock *PersonStoreMock) Create(ctx context.Context, person *example.Person, confirm bool) error", 138 "func (mock *PersonStoreMock) Get(ctx context.Context, id string) (*example.Person, error)", 139 } 140 for _, str := range strs { 141 if !strings.Contains(s, str) { 142 t.Errorf("expected but missing: \"%s\"", str) 143 } 144 } 145 } 146 147 func TestMoqExplicitPackageWithStaticCheck(t *testing.T) { 148 m, err := New(Config{SrcDir: "testpackages/example", PkgName: "different"}) 149 if err != nil { 150 t.Fatalf("moq.New: %s", err) 151 } 152 var buf bytes.Buffer 153 err = m.Mock(&buf, "PersonStore") 154 if err != nil { 155 t.Errorf("m.Mock: %s", err) 156 } 157 s := buf.String() 158 // assertions of things that should be mentioned 159 strs := []string{ 160 "package different", 161 "var _ example.PersonStore = &PersonStoreMock{}", 162 "type PersonStoreMock struct", 163 "CreateFunc func(ctx context.Context, person *example.Person, confirm bool) error", 164 "GetFunc func(ctx context.Context, id string) (*example.Person, error)", 165 "func (mock *PersonStoreMock) Create(ctx context.Context, person *example.Person, confirm bool) error", 166 "func (mock *PersonStoreMock) Get(ctx context.Context, id string) (*example.Person, error)", 167 } 168 for _, str := range strs { 169 if !strings.Contains(s, str) { 170 t.Errorf("expected but missing: \"%s\"", str) 171 } 172 } 173 } 174 175 func TestMoqSkipEnsure(t *testing.T) { 176 m, err := New(Config{SrcDir: "testpackages/example", PkgName: "different", SkipEnsure: true}) 177 if err != nil { 178 t.Fatalf("moq.New: %s", err) 179 } 180 var buf bytes.Buffer 181 err = m.Mock(&buf, "PersonStore") 182 if err != nil { 183 t.Errorf("m.Mock: %s", err) 184 } 185 s := buf.String() 186 // assertions of things that should be mentioned 187 strs := []string{ 188 "package different", 189 "type PersonStoreMock struct", 190 "CreateFunc func(ctx context.Context, person *example.Person, confirm bool) error", 191 "GetFunc func(ctx context.Context, id string) (*example.Person, error)", 192 "func (mock *PersonStoreMock) Create(ctx context.Context, person *example.Person, confirm bool) error", 193 "func (mock *PersonStoreMock) Get(ctx context.Context, id string) (*example.Person, error)", 194 } 195 for _, str := range strs { 196 if !strings.Contains(s, str) { 197 t.Errorf("expected but missing: \"%s\"", str) 198 } 199 } 200 } 201 202 func TestNotCreatingEmptyDirWhenPkgIsGiven(t *testing.T) { 203 m, err := New(Config{SrcDir: "testpackages/example", PkgName: "different"}) 204 if err != nil { 205 t.Fatalf("moq.New: %s", err) 206 } 207 var buf bytes.Buffer 208 err = m.Mock(&buf, "PersonStore") 209 if err != nil { 210 t.Errorf("m.Mock: %s", err) 211 } 212 s := buf.String() 213 if len(s) == 0 { 214 t.Fatalf("mock should be generated") 215 } 216 if _, err := os.Stat("testpackages/example/different"); !os.IsNotExist(err) { 217 t.Fatalf("no empty dir should be created by moq") 218 } 219 } 220 221 // TestVariadicArguments tests to ensure variadic work as 222 // expected. 223 // see https://github.com/matryer/moq/issues/5 224 func TestVariadicArguments(t *testing.T) { 225 m, err := New(Config{SrcDir: "testpackages/variadic"}) 226 if err != nil { 227 t.Fatalf("moq.New: %s", err) 228 } 229 var buf bytes.Buffer 230 err = m.Mock(&buf, "Greeter") 231 if err != nil { 232 t.Errorf("m.Mock: %s", err) 233 } 234 s := buf.String() 235 // assertions of things that should be mentioned 236 strs := []string{ 237 "package variadic", 238 "type GreeterMock struct", 239 "GreetFunc func(ctx context.Context, names ...string) string", 240 "return mock.GreetFunc(ctx, names...)", 241 } 242 for _, str := range strs { 243 if !strings.Contains(s, str) { 244 t.Errorf("expected but missing: \"%s\"", str) 245 } 246 } 247 } 248 249 func TestNothingToReturn(t *testing.T) { 250 m, err := New(Config{SrcDir: "testpackages/example"}) 251 if err != nil { 252 t.Fatalf("moq.New: %s", err) 253 } 254 var buf bytes.Buffer 255 err = m.Mock(&buf, "PersonStore") 256 if err != nil { 257 t.Errorf("m.Mock: %s", err) 258 } 259 s := buf.String() 260 if strings.Contains(s, `return mock.ClearCacheFunc(id)`) { 261 t.Errorf("should not have return for items that have no return arguments") 262 } 263 // assertions of things that should be mentioned 264 strs := []string{ 265 "mock.ClearCacheFunc(id)", 266 } 267 for _, str := range strs { 268 if !strings.Contains(s, str) { 269 t.Errorf("expected but missing: \"%s\"", str) 270 } 271 } 272 } 273 274 func TestImports(t *testing.T) { 275 m, err := New(Config{SrcDir: "testpackages/imports/two"}) 276 if err != nil { 277 t.Fatalf("moq.New: %s", err) 278 } 279 var buf bytes.Buffer 280 err = m.Mock(&buf, "DoSomething") 281 if err != nil { 282 t.Errorf("m.Mock: %s", err) 283 } 284 s := buf.String() 285 strs := []string{ 286 ` "sync"`, 287 ` "github.com/moitias/moq/pkg/moq/testpackages/imports/one"`, 288 } 289 for _, str := range strs { 290 if !strings.Contains(s, str) { 291 t.Errorf("expected but missing: \"%s\"", str) 292 } 293 if len(strings.Split(s, str)) > 2 { 294 t.Errorf("more than one: \"%s\"", str) 295 } 296 } 297 } 298 299 func TestMockGolden(t *testing.T) { 300 cases := []struct { 301 name string 302 cfg Config 303 interfaces []string 304 goldenFile string 305 }{ 306 { 307 // Tests to ensure slice return data type works as expected. 308 // See https://github.com/matryer/moq/issues/124 309 name: "SliceResult", 310 cfg: Config{SrcDir: "testpackages/variadic"}, 311 interfaces: []string{"Echoer"}, 312 goldenFile: filepath.Join("testpackages/variadic", "echoer.golden.go"), 313 }, 314 { 315 // Tests generation of mock where a method on the interface uses a 316 // blank identifier. 317 // See https://github.com/matryer/moq/issues/70 318 name: "BlankID", 319 cfg: Config{SrcDir: "testpackages/blankid"}, 320 interfaces: []string{"Swallower"}, 321 goldenFile: filepath.Join("testpackages/blankid", "swallower.golden.go"), 322 }, 323 { 324 name: "ChannelNames", 325 cfg: Config{SrcDir: "testpackages/channels", StubImpl: true}, 326 interfaces: []string{"Queuer"}, 327 goldenFile: filepath.Join("testpackages/channels", "queuer_moq.golden.go"), 328 }, 329 { 330 // Tests generation of mock when the interface imports a different 331 // package by the same name as it's own. 332 // See https://github.com/matryer/moq/issues/94 333 name: "PkgShadow", 334 cfg: Config{SrcDir: "testpackages/shadow/http", PkgName: "mock"}, 335 interfaces: []string{"Thing"}, 336 goldenFile: filepath.Join("testpackages/shadow/mock", "thing_moq.golden.go"), 337 }, 338 { 339 // Tests generation of mock when a method parameter shadows an 340 // imported package name. 341 name: "ParamShadow", 342 cfg: Config{SrcDir: "testpackages/shadow"}, 343 interfaces: []string{"Shadower"}, 344 goldenFile: filepath.Join("testpackages/shadow", "shadower_moq.golden.go"), 345 }, 346 { 347 name: "ImportAlias", 348 cfg: Config{SrcDir: "testpackages/importalias"}, 349 interfaces: []string{"MiddleMan"}, 350 goldenFile: filepath.Join("testpackages/importalias", "middleman_moq.golden.go"), 351 }, 352 { 353 // Tests conflict resolution for generated names of method 354 // parameters. 355 name: "ParamNameConflict", 356 cfg: Config{SrcDir: "testpackages/paramconflict"}, 357 interfaces: []string{"Interface"}, 358 goldenFile: filepath.Join("testpackages/paramconflict", "iface_moq.golden.go"), 359 }, 360 { 361 // Tests generation of names for unnamed method parameters. 362 name: "GenerateParamNames", 363 cfg: Config{SrcDir: "testpackages/genparamname"}, 364 interfaces: []string{"Interface"}, 365 goldenFile: filepath.Join("testpackages/genparamname", "iface_moq.golden.go"), 366 }, 367 { 368 name: "SyncImport", 369 cfg: Config{SrcDir: "testpackages/syncimport"}, 370 interfaces: []string{"Syncer"}, 371 goldenFile: filepath.Join("testpackages/syncimport", "syncer_moq.golden.go"), 372 }, 373 { 374 // Tests anonymous imports are not included in the generated mock. 375 name: "AnonymousImport", 376 cfg: Config{SrcDir: "testpackages/anonimport"}, 377 interfaces: []string{"Example"}, 378 goldenFile: filepath.Join("testpackages/anonimport", "iface_moq.golden.go"), 379 }, 380 { 381 name: "ShadowTypes", 382 cfg: Config{SrcDir: "testpackages/shadowtypes"}, 383 interfaces: []string{"ShadowTypes"}, 384 goldenFile: filepath.Join("testpackages/shadowtypes", "shadowtypes_moq.golden.go"), 385 }, 386 { 387 name: "Generics", 388 cfg: Config{SrcDir: "testpackages/generics"}, 389 interfaces: []string{"GenericStore1", "GenericStore2", "AliasStore"}, 390 goldenFile: filepath.Join("testpackages/generics", "generics_moq.golden.go"), 391 }, 392 { 393 name: "Generic Return Argument Type", 394 cfg: Config{SrcDir: "testpackages/genericreturn"}, 395 interfaces: []string{"IFooBar"}, 396 goldenFile: filepath.Join("testpackages/genericreturn", "genericreturn.golden.go"), 397 }, 398 { 399 name: "TransientImport", 400 cfg: Config{SrcDir: "testpackages/transientimport"}, 401 interfaces: []string{"Transient"}, 402 goldenFile: filepath.Join("testpackages/transientimport", "transient_moq.golden.go"), 403 }, 404 { 405 name: "WithResets", 406 cfg: Config{SrcDir: "testpackages/withresets", WithResets: true}, 407 interfaces: []string{"ResetStore"}, 408 goldenFile: filepath.Join("testpackages/withresets", "withresets_moq.golden.go"), 409 }, 410 } 411 for _, tc := range cases { 412 t.Run(tc.name, func(t *testing.T) { 413 m, err := New(tc.cfg) 414 if err != nil { 415 t.Fatalf("moq.New: %s", err) 416 } 417 418 var buf bytes.Buffer 419 if err = m.Mock(&buf, tc.interfaces...); err != nil { 420 t.Errorf("m.Mock: %s", err) 421 return 422 } 423 424 if err := matchGoldenFile(tc.goldenFile, buf.Bytes()); err != nil { 425 t.Errorf("check golden file: %s", err) 426 } 427 }) 428 } 429 } 430 431 func TestFormatter(t *testing.T) { 432 cases := []struct { 433 name string 434 conf Config 435 }{ 436 {name: "gofmt", conf: Config{SrcDir: "testpackages/imports/two"}}, 437 {name: "goimports", conf: Config{SrcDir: "testpackages/imports/two", Formatter: "goimports"}}, 438 {name: "noop", conf: Config{SrcDir: "testpackages/imports/two", Formatter: "noop"}}, 439 } 440 for _, tc := range cases { 441 t.Run(tc.name, func(t *testing.T) { 442 m, err := New(tc.conf) 443 if err != nil { 444 t.Fatalf("moq.New: %s", err) 445 } 446 var buf bytes.Buffer 447 err = m.Mock(&buf, "DoSomething:"+tc.name+"Mock") 448 if err != nil { 449 t.Errorf("m.Mock: %s", err) 450 } 451 452 golden := filepath.Join("testpackages/imports/two", tc.name+".golden.go") 453 if err := matchGoldenFile(golden, buf.Bytes()); err != nil { 454 t.Errorf("check golden file: %s", err) 455 } 456 }) 457 } 458 } 459 460 func matchGoldenFile(goldenFile string, actual []byte) error { 461 // To update golden files, run the following: 462 // go test -v -run '^<Test-Name>$' github.com/matryer/moq/pkg/moq -update 463 if *update { 464 if err := os.MkdirAll(filepath.Dir(goldenFile), 0o750); err != nil { 465 return fmt.Errorf("create dir: %s", err) 466 } 467 if err := ioutil.WriteFile(goldenFile, actual, 0o600); err != nil { 468 return fmt.Errorf("write: %s", err) 469 } 470 471 return nil 472 } 473 474 expected, err := ioutil.ReadFile(goldenFile) 475 if err != nil { 476 return fmt.Errorf("read: %s: %s", goldenFile, err) 477 } 478 479 // Normalise newlines 480 actual, expected = normalize(actual), normalize(expected) 481 if !bytes.Equal(expected, actual) { 482 diff, err := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{ 483 A: difflib.SplitLines(string(expected)), 484 B: difflib.SplitLines(string(actual)), 485 FromFile: "Expected", 486 ToFile: "Actual", 487 Context: 1, 488 }) 489 if err != nil { 490 return fmt.Errorf("diff: %s", err) 491 } 492 return fmt.Errorf("match: %s:\n%s", goldenFile, diff) 493 } 494 495 return nil 496 } 497 498 func TestVendoredPackages(t *testing.T) { 499 m, err := New(Config{SrcDir: "testpackages/vendoring/user"}) 500 if err != nil { 501 t.Fatalf("moq.New: %s", err) 502 } 503 var buf bytes.Buffer 504 err = m.Mock(&buf, "Service") 505 if err != nil { 506 t.Errorf("mock error: %s", err) 507 } 508 s := buf.String() 509 // assertions of things that should be mentioned 510 strs := []string{ 511 `"github.com/sudo-suhas/moq-test-pkgs/somerepo"`, 512 } 513 for _, str := range strs { 514 if !strings.Contains(s, str) { 515 t.Errorf("expected but missing: \"%s\"", str) 516 } 517 } 518 } 519 520 func TestVendoredInterface(t *testing.T) { 521 m, err := New(Config{ 522 SrcDir: "testpackages/vendoring/vendor/github.com/sudo-suhas/moq-test-pkgs/somerepo", 523 PkgName: "someother", 524 }) 525 if err != nil { 526 t.Fatalf("moq.New: %s", err) 527 } 528 var buf bytes.Buffer 529 err = m.Mock(&buf, "SomeService") 530 if err != nil { 531 t.Errorf("mock error: %s", err) 532 } 533 s := buf.String() 534 // assertions of things that should be mentioned 535 strs := []string{ 536 `"github.com/sudo-suhas/moq-test-pkgs/somerepo"`, 537 } 538 for _, str := range strs { 539 if !strings.Contains(s, str) { 540 t.Errorf("expected but missing: \"%s\"", str) 541 } 542 } 543 incorrectImport := `"github.com/moitias/moq/pkg/moq/testpackages/vendoring/vendor/github.com/sudo-suhas/moq-test-pkgs/somerepo"` 544 if strings.Contains(s, incorrectImport) { 545 t.Errorf("unexpected import: %s", incorrectImport) 546 } 547 } 548 549 func TestVendoredBuildConstraints(t *testing.T) { 550 m, err := New(Config{SrcDir: "testpackages/buildconstraints/user"}) 551 if err != nil { 552 t.Fatalf("moq.New: %s", err) 553 } 554 var buf bytes.Buffer 555 err = m.Mock(&buf, "Service") 556 if err != nil { 557 t.Errorf("mock error: %s", err) 558 } 559 s := buf.String() 560 // assertions of things that should be mentioned 561 strs := []string{ 562 `"github.com/sudo-suhas/moq-test-pkgs/buildconstraints"`, 563 } 564 for _, str := range strs { 565 if !strings.Contains(s, str) { 566 t.Errorf("expected but missing: \"%s\"", str) 567 } 568 } 569 } 570 571 // TestDotImports tests for https://github.com/matryer/moq/issues/21. 572 func TestDotImports(t *testing.T) { 573 preDir, err := os.Getwd() 574 if err != nil { 575 t.Errorf("Getwd: %s", err) 576 } 577 err = os.Chdir("testpackages/dotimport") 578 if err != nil { 579 t.Errorf("Chdir: %s", err) 580 } 581 defer func() { 582 err := os.Chdir(preDir) 583 if err != nil { 584 t.Errorf("Chdir back: %s", err) 585 } 586 }() 587 m, err := New(Config{SrcDir: ".", PkgName: "moqtest_test"}) 588 if err != nil { 589 t.Fatalf("moq.New: %s", err) 590 } 591 var buf bytes.Buffer 592 err = m.Mock(&buf, "Service") 593 if err != nil { 594 t.Errorf("mock error: %s", err) 595 } 596 s := buf.String() 597 if strings.Contains(s, `"."`) { 598 t.Error("contains invalid dot import") 599 } 600 } 601 602 func TestEmptyInterface(t *testing.T) { 603 m, err := New(Config{SrcDir: "testpackages/emptyinterface"}) 604 if err != nil { 605 t.Fatalf("moq.New: %s", err) 606 } 607 var buf bytes.Buffer 608 err = m.Mock(&buf, "Empty") 609 if err != nil { 610 t.Errorf("mock error: %s", err) 611 } 612 s := buf.String() 613 if strings.Contains(s, `"sync"`) { 614 t.Error("contains sync import, although this package isn't used") 615 } 616 } 617 618 func TestGoGenerateVendoredPackages(t *testing.T) { 619 cmd := exec.Command("go", "generate", "./...") 620 cmd.Dir = "testpackages/gogenvendoring" 621 stdout, err := cmd.StdoutPipe() 622 if err != nil { 623 t.Errorf("StdoutPipe: %s", err) 624 } 625 defer stdout.Close() 626 err = cmd.Start() 627 if err != nil { 628 t.Errorf("Start: %s", err) 629 } 630 buf := bytes.NewBuffer(nil) 631 io.Copy(buf, stdout) 632 err = cmd.Wait() 633 if err != nil { 634 if exitErr, ok := err.(*exec.ExitError); ok { 635 t.Errorf("Wait: %s %s", exitErr, string(exitErr.Stderr)) 636 } else { 637 t.Errorf("Wait: %s", err) 638 } 639 } 640 s := buf.String() 641 if strings.Contains(s, `vendor/`) { 642 t.Error("contains vendor directory in import path") 643 } 644 } 645 646 func TestImportedPackageWithSameName(t *testing.T) { 647 m, err := New(Config{SrcDir: "testpackages/samenameimport"}) 648 if err != nil { 649 t.Fatalf("moq.New: %s", err) 650 } 651 var buf bytes.Buffer 652 err = m.Mock(&buf, "Example") 653 if err != nil { 654 t.Errorf("mock error: %s", err) 655 } 656 s := buf.String() 657 if !strings.Contains(s, `a samename.A`) { 658 t.Error("missing samename.A to address the struct A from the external package samename") 659 } 660 } 661 662 func TestParseError(t *testing.T) { 663 _, err := New(Config{SrcDir: "testpackages/_parseerror/service"}) 664 if err == nil { 665 t.Errorf("expected error but got nil") 666 return 667 } 668 // The first clause is the common error. Only in go version 1.19.10 the error differs 669 if !strings.Contains(err.Error(), `could not import github.com/matryer/notexist (invalid package name: "")`) && !strings.Contains(err.Error(), "stderr: go build github.com/matryer/notexist") { 670 t.Errorf("unexpected error: %s", err.Error()) 671 } 672 } 673 674 func TestMockError(t *testing.T) { 675 m, err := New(Config{SrcDir: "testpackages/example"}) 676 if err != nil { 677 t.Fatalf("moq.New: %s", err) 678 } 679 cases := []struct { 680 name string 681 namePair string 682 wantErr string 683 }{ 684 { 685 name: "TypeNotFound", 686 namePair: "DoesNotExist", 687 wantErr: "interface not found: DoesNotExist", 688 }, 689 { 690 name: "UnexpectedType", 691 namePair: "Person", 692 wantErr: "Person (github.com/matryer/moq/pkg/moq/testpackages/example.Person) is not an interface", 693 }, 694 } 695 for _, tc := range cases { 696 t.Run(tc.name, func(t *testing.T) { 697 err := m.Mock(ioutil.Discard, tc.namePair) 698 if err == nil { 699 t.Errorf("expected error but got nil") 700 return 701 } 702 if !strings.Contains(err.Error(), tc.wantErr) { 703 t.Errorf("unexpected error: %s", err.Error()) 704 } 705 }) 706 } 707 } 708 709 // normalize normalizes \r\n (windows) and \r (mac) 710 // into \n (unix) 711 func normalize(d []byte) []byte { 712 // Source: https://www.programming-books.io/essential/go/normalize-newlines-1d3abcf6f17c4186bb9617fa14074e48 713 // replace CR LF \r\n (windows) with LF \n (unix) 714 d = bytes.Replace(d, []byte{13, 10}, []byte{10}, -1) 715 // replace CF \r (mac) with LF \n (unix) 716 d = bytes.Replace(d, []byte{13}, []byte{10}, -1) 717 return d 718 }