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 }