1 module mocked.tests.alien; 2 3 import dshould; 4 import mocked; 5 import unit_threaded : DontTest, ShouldFail; 6 7 version (unittest) 8 { 9 class Templated(T) 10 { 11 } 12 13 interface IM 14 { 15 void bar(); 16 } 17 18 class ConstructorArg 19 { 20 int a; 21 22 this(int i) 23 { 24 this.a = i; 25 } 26 27 int getA() 28 { 29 return this.a; 30 } 31 } 32 33 class SimpleObject 34 { 35 this() 36 { 37 } 38 39 void print() 40 { 41 import std.stdio : writeln; 42 43 writeln(toString()); 44 } 45 } 46 47 interface IRM 48 { 49 IM get(); 50 void set(IM im); 51 } 52 53 class HasPrivateMethods 54 { 55 protected void method() 56 { 57 } 58 } 59 60 interface IFace 61 { 62 void foo(string s); 63 } 64 65 class Smthng : IFace 66 { 67 void foo(string) 68 { 69 } 70 } 71 72 class HasMember 73 { 74 int member; 75 } 76 77 class Overloads 78 { 79 void foo() 80 { 81 } 82 83 void foo(int) 84 { 85 } 86 } 87 88 class Qualifiers 89 { 90 int make() shared 91 { 92 return 0; 93 } 94 95 int make() const 96 { 97 return 1; 98 } 99 100 int make() shared const 101 { 102 return 2; 103 } 104 105 int make() 106 { 107 return 3; 108 } 109 110 int make() immutable 111 { 112 return 4; 113 } 114 } 115 116 interface VirtualFinal 117 { 118 int makeVir(); 119 } 120 121 class MakeAbstract 122 { 123 int con; 124 this(int con) 125 { 126 this.con = con; 127 } 128 129 abstract int abs(); 130 131 int concrete() 132 { 133 return con; 134 } 135 } 136 137 class FinalMethods : VirtualFinal 138 { 139 final int make() 140 { 141 return 0; 142 } 143 144 final int make(int) 145 { 146 return 2; 147 } 148 149 int makeVir() 150 { 151 return 5; 152 } 153 } 154 155 final class FinalClass 156 { 157 int fortyTwo() 158 { 159 return 42; 160 } 161 } 162 163 class TemplateMethods 164 { 165 string get(T)(T) 166 { 167 import std.traits : fullyQualifiedName; 168 169 return fullyQualifiedName!T; 170 } 171 172 int getSomethings(T...)(T) 173 { 174 return T.length; 175 } 176 } 177 178 struct Struct 179 { 180 int get() 181 { 182 return 1; 183 } 184 } 185 186 struct StructWithFields 187 { 188 int field; 189 190 int get() 191 { 192 return field; 193 } 194 } 195 196 struct StructWithConstructor 197 { 198 int field; 199 200 this(int i) 201 { 202 field = i; 203 } 204 205 int get() 206 { 207 return field; 208 } 209 } 210 211 class Dependency 212 { 213 private int[] arr = [1, 2]; 214 private int index = 0; 215 public int foo() 216 { 217 return arr[index++]; 218 } 219 } 220 221 class TakesFloat 222 { 223 public void foo(float) 224 { 225 } 226 } 227 228 class Property 229 { 230 private int _foo; 231 232 @property int foo() 233 { 234 return _foo; 235 } 236 237 @property void foo(int i) 238 { 239 _foo = i; 240 } 241 242 @property T foot(T)() 243 { 244 static if (is(T == int)) 245 { 246 return _foo; 247 } 248 else 249 { 250 return T.init; 251 } 252 } 253 254 @property void foot(T)(T i) 255 { 256 static if (is(T == int)) 257 { 258 _foo = i; 259 } 260 } 261 } 262 263 } 264 265 @("nontemplated mock") 266 unittest 267 { 268 Mocker().mock!(Object)(); 269 } 270 271 @("templated mock") 272 unittest 273 { 274 static assert(is(typeof(Mocker().mock!(Templated!(int))()))); 275 } 276 277 @("interface mock") 278 unittest 279 { 280 static assert(is(typeof(Mocker().mock!IM()))); 281 } 282 283 @("constructor argument") 284 unittest 285 { 286 Mocker mocker; 287 288 static assert(is(typeof(mocker.mock!(ConstructorArg)(4)))); 289 } 290 291 @DontTest 292 class TestClass 293 { 294 string test() 295 { 296 return "test"; 297 } 298 299 string test1() 300 { 301 return "test 1"; 302 } 303 304 string test2() 305 { 306 return "test 2"; 307 } 308 309 int test_int(int i) 310 { 311 return i; 312 } 313 } 314 315 @("unexpected call") 316 unittest 317 { 318 Mocker mocker; 319 TestClass cl = mocker.mock!(TestClass); 320 321 cl.test.should.throwA!UnexpectedCallError; 322 mocker.verify; 323 } 324 325 @ShouldFail("expect") 326 unittest 327 { 328 Mocker mocker; 329 auto cl = mocker.mock!(TestClass); 330 cl.expect.test().repeat(0).returns("mrow?"); 331 332 cl.test; 333 } 334 335 @("expect mismatched type") 336 version (none) unittest 337 { 338 Mocker mocker; 339 TestClass cl = mocker.mock!(TestClass); 340 341 void call_test(T)(T arg) 342 { 343 mocker.expectT!(cl, "test_int")(arg); 344 } 345 346 static assert(__traits(compiles, call_test(5))); 347 static assert(!__traits(compiles, call_test("string"))); 348 349 void return_test(T)(T arg) 350 { 351 mocker.expectT!(cl, "test_int")(5).returns(arg); 352 } 353 354 static assert(__traits(compiles, return_test(5))); 355 static assert(!__traits(compiles, return_test("string"))); 356 } 357 358 @("repeat single") 359 unittest 360 { 361 Mocker mocker; 362 auto cl = mocker.mock!(TestClass); 363 cl.expect.test().repeat(2).returns("foom?"); 364 365 cl.test; 366 cl.test; 367 368 cl.test.should.throwAn!UnexpectedCallError; 369 } 370 371 @ShouldFail("repository match counts") 372 unittest 373 { 374 Mocker mocker; 375 auto cl = mocker.mock!TestClass; 376 377 cl.expect.test().repeat(2).returns("mew."); 378 379 mocker.verify(); 380 } 381 382 @("delegate payload") 383 unittest 384 { 385 bool calledPayload = false; 386 Mocker mocker; 387 auto obj = mocker.mock!SimpleObject; 388 389 obj.expect.print().action({ calledPayload = true; }); 390 391 obj.print; 392 393 calledPayload.should.be(true); 394 } 395 396 @("delegate payload with mismatching parameters") 397 unittest 398 { 399 Mocker mocker; 400 auto obj = mocker.mock!SimpleObject; 401 402 static assert(!is(typeof(obj.expect.print().action((int) {})))); 403 } 404 405 @("exception payload") 406 unittest 407 { 408 Mocker mocker; 409 auto obj = mocker.mock!(SimpleObject); 410 411 enum string msg = "divide by cucumber error"; 412 obj.expect.print().throws(new Exception(msg)); 413 414 obj.print.should.throwAn!Exception.where.msg.should.equal(msg); 415 } 416 417 @("passthrough") 418 unittest 419 { 420 Mocker mocker; 421 auto cl = mocker.mock!(TestClass); 422 cl.expect.test().passThrough; 423 424 string str = cl.test; 425 str.should.equal("test"); 426 } 427 428 @("class with constructor init check") 429 unittest 430 { 431 Mocker mocker; 432 auto obj = mocker.mock!ConstructorArg(4); 433 434 obj.expect.getA().passThrough; 435 436 obj.getA().should.equal(4); 437 } 438 439 @("associative arrays") 440 unittest 441 { 442 Mocker mocker; 443 444 auto mock = mocker.mock!(Object); 445 mock.expect.toHash.passThrough().repeatAny; 446 mock.expect.opEquals.passThrough().repeatAny; 447 448 auto obj = mock.get; 449 450 int[Object] i; 451 i[obj] = 5; 452 int j = i[obj]; 453 } 454 455 @("ordering in order") 456 version (none) unittest 457 { 458 Mocker mocker; 459 auto obj = mocker.mock!(Object); 460 mocker.ordered; 461 mocker.expect(obj.toHash).returns(cast(hash_t) 5); 462 mocker.expect(obj.toString).returns("mow!"); 463 464 mocker.replay(); 465 obj.toHash; 466 obj.toString; 467 mocker.verify; 468 } 469 470 @("ordering not in order") 471 version (none) unittest 472 { 473 Mocker mocker; 474 auto cl = mocker.mock!(TestClass); 475 mocker.ordered; 476 mocker.expect(cl.test1).returns("mew!"); 477 mocker.expect(cl.test2).returns("mow!"); 478 479 mocker.replay(); 480 481 assertThrown!ExpectationViolationError(cl.test2); 482 } 483 484 @("ordering interposed") 485 version (none) unittest 486 { 487 Mocker mocker; 488 auto obj = mocker.mock!(SimpleObject); 489 mocker.ordered; 490 mocker.expect(obj.toHash).returns(cast(hash_t) 5); 491 mocker.expect(obj.toString).returns("mow!"); 492 mocker.unordered; 493 obj.print; 494 495 mocker.replay(); 496 obj.toHash; 497 obj.print; 498 obj.toString; 499 } 500 501 @("allow unexpected") 502 version (none) unittest 503 { 504 Mocker mocker; 505 auto obj = mocker.mock!(Object); 506 mocker.ordered; 507 mocker.allowUnexpectedCalls(true); 508 mocker.expect(obj.toString).returns("mow!"); 509 mocker.replay(); 510 obj.toHash; // unexpected tohash calls 511 obj.toString; 512 obj.toHash; 513 assertThrown!ExpectationViolationError(mocker.verify(false, true)); 514 mocker.verify(true, false); 515 } 516 517 @("allowing") 518 version (none) unittest 519 { 520 Mocker mocker; 521 auto obj = mocker.mock!(Object); 522 mocker.allowing(obj.toString).returns("foom?"); 523 524 mocker.replay(); 525 obj.toString; 526 obj.toString; 527 obj.toString; 528 mocker.verify; 529 } 530 531 @("nothing for method to do") 532 version (none) unittest 533 { 534 try 535 { 536 Mocker mocker; 537 auto cl = mocker.mock!(TestClass); 538 mocker.allowing(cl.test); 539 540 mocker.replay(); 541 assert(false, "expected a mocks setup exception"); 542 } 543 catch (MocksSetupException e) 544 { 545 } 546 } 547 548 @("allow defaults test") 549 version (none) unittest 550 { 551 Mocker mocker; 552 auto cl = mocker.mock!(TestClass); 553 mocker.allowDefaults; 554 mocker.allowing(cl.test); 555 556 mocker.replay(); 557 assert(cl.test == (char[]).init); 558 } 559 560 @("mock interface") 561 unittest 562 { 563 Mocker mocker; 564 auto obj = mocker.mock!IFace; 565 566 obj.expect.foo("hallo"); 567 568 obj.get.foo("hallo"); 569 570 mocker.verify; 571 } 572 573 @("cast mock to interface") 574 unittest 575 { 576 Mocker mocker; 577 auto obj = mocker.mock!Smthng; 578 579 obj.expect.foo("hallo"); 580 581 obj.get.foo("hallo"); 582 583 mocker.verify; 584 } 585 586 @("cast mock to interface") 587 unittest 588 { 589 Mocker mocker; 590 auto obj = mocker.mock!Smthng; 591 592 obj.expect.foo("hallo"); 593 594 obj.foo("hallo"); 595 596 mocker.verify; 597 } 598 599 @("return user-defined type") 600 unittest 601 { 602 Mocker mocker; 603 604 auto objBuilder = mocker.mock!IRM; 605 auto obj = objBuilder.get; 606 607 auto imBuilder = mocker.mock!IM; 608 auto im = imBuilder.get; 609 610 objBuilder.expect.get().returns(im); 611 objBuilder.expect.set(im); 612 613 obj.get.should.be(im); 614 obj.set(im); 615 mocker.verify; 616 } 617 618 @("return user-defined type") 619 unittest 620 { 621 Mocker mocker; 622 mocker.mock!HasMember; 623 } 624 625 @("overloaded method") 626 unittest 627 { 628 Mocker mocker; 629 auto obj = mocker.mock!(Overloads); 630 obj.expect.foo(); 631 obj.expect.foo(1); 632 633 obj.foo(1); 634 obj.foo; 635 636 mocker.verify; 637 } 638 639 @("overloaded method qualifiers") 640 version (none) unittest 641 { 642 { 643 auto mocker = new Mocker; 644 auto s = mocker.mock!(shared(Qualifiers)); 645 auto sc = cast(shared const) s; 646 647 mocker.expect(s.make).passThrough; 648 mocker.expect(sc.make).passThrough; 649 mocker.replay; 650 651 assert(s.make == 0); 652 assert(sc.make == 2); 653 654 mocker.verify; 655 } 656 { 657 auto mocker = new Mocker; 658 auto m = mocker.mock!(Qualifiers); 659 auto c = cast(const) m; 660 auto i = cast(immutable) m; 661 662 mocker.expect(i.make).passThrough; 663 mocker.expect(m.make).passThrough; 664 mocker.expect(c.make).passThrough; 665 mocker.replay; 666 667 assert(i.make == 4); 668 assert(m.make == 3); 669 assert(c.make == 1); 670 671 mocker.verify; 672 } 673 { 674 auto mocker = new Mocker; 675 auto m = mocker.mock!(Qualifiers); 676 auto c = cast(const) m; 677 auto i = cast(immutable) m; 678 679 mocker.expect(i.make).passThrough; 680 mocker.expect(m.make).passThrough; 681 mocker.expect(m.make).passThrough; 682 mocker.replay; 683 684 assert(i.make == 4); 685 assert(m.make == 3); 686 assertThrown!ExpectationViolationError(c.make); 687 } 688 } 689 690 @("final mock of virtual methods") 691 version (none) unittest 692 { 693 auto mocker = new Mocker; 694 auto obj = mocker.mockFinal!(VirtualFinal); 695 mocker.expect(obj.makeVir()).returns(5); 696 mocker.replay; 697 assert(obj.makeVir == 5); 698 } 699 700 @("final mock of abstract methods") 701 version (none) unittest 702 { 703 auto mocker = new Mocker; 704 auto obj = mocker.mockFinal!(MakeAbstract)(6); 705 mocker.expect(obj.concrete()).passThrough; 706 mocker.replay; 707 assert(obj.concrete == 6); 708 mocker.verify; 709 } 710 711 @("final methods") 712 version (none) unittest 713 { 714 auto mocker = new Mocker; 715 auto obj = mocker.mockFinal!(FinalMethods); 716 mocker.expect(obj.make()).passThrough; 717 mocker.expect(obj.make(1)).passThrough; 718 mocker.replay; 719 static assert(!is(typeof(o) == FinalMethods)); 720 assert(obj.make == 0); 721 assert(obj.make(1) == 2); 722 mocker.verify; 723 } 724 725 @("final class") 726 version (none) unittest 727 { 728 auto mocker = new Mocker; 729 auto obj = mocker.mockFinal!(FinalClass); 730 mocker.expect(obj.fortyTwo()).passThrough; 731 mocker.replay; 732 assert(obj.fortyTwo == 42); 733 mocker.verify; 734 } 735 736 @("final class with no underlying object") 737 version (none) unittest 738 { 739 auto mocker = new Mocker; 740 auto obj = mocker.mockFinalPassTo!(FinalClass)(null); 741 mocker.expect(obj.fortyTwo()).returns(43); 742 mocker.replay; 743 assert(obj.fortyTwo == 43); 744 mocker.verify; 745 } 746 747 @("template methods") 748 version (none) unittest 749 { 750 auto mocker = new Mocker; 751 auto obj = mocker.mockFinal!(TemplateMethods); 752 mocker.expect(obj.get(1)).passThrough; 753 mocker.expect(obj.getSomethings(1, 2, 3)).passThrough; 754 mocker.replay; 755 assert(obj.get(1) == "int"); 756 auto tm = new TemplateMethods(); 757 assert(obj.getSomethings(1, 2, 3) == 3); 758 mocker.verify; 759 } 760 761 @("returning different values on the same expectation") 762 unittest 763 { 764 Mocker mocker; 765 auto dependency = mocker.mock!Dependency; 766 767 //mocker.ordered; 768 dependency.expect.foo.returns(1); 769 dependency.expect.foo.returns(2); 770 771 dependency.foo.should.equal(1); 772 dependency.foo.should.equal(2); 773 774 mocker.verify; 775 } 776 777 @("customArgsComparator") 778 unittest 779 { 780 import std.math : abs; 781 782 enum float argument = 1.0f; 783 784 auto mocker = configure!(Comparator!((float a, float b) => abs(a - b) < 0.1f)); 785 auto dependency = mocker.mock!TakesFloat; 786 dependency.expect.foo(argument).repeat(2); 787 788 // custom comparison example - treat similar floats as equals 789 dependency.foo(1.01); 790 dependency.foo(1.02); 791 }