1 module unit_threaded.ut.mock;
2 
3 import unit_threaded.mock;
4 
5 @("mock interface verify fails")
6 @safe pure unittest {
7     import unit_threaded.asserts;
8 
9     interface Foo {
10         int foo(int, string) @safe pure;
11         void bar() @safe pure;
12     }
13 
14     int fun(Foo f) {
15         return 2 * f.foo(5, "foobar");
16     }
17 
18     {
19         auto m = mock!Foo;
20         m.expect!"foo"(6, "foobar");
21         fun(m);
22         assertExceptionMsg(m.verify,
23                            `    tests/unit_threaded/ut/mock.d:123 - foo was called with unexpected Tuple!(int, string)(5, "foobar")` ~ "\n" ~
24                            `    tests/unit_threaded/ut/mock.d:123 -        instead of the expected Tuple!(int, string)(6, "foobar")`);
25     }
26 
27     {
28         auto m = mock!Foo;
29         m.expect!"foo"(5, "quux");
30         fun(m);
31         assertExceptionMsg(m.verify,
32                            `    tests/unit_threaded/ut/mock.d:123 - foo was called with unexpected Tuple!(int, string)(5, "foobar")` ~ "\n" ~
33                            `    tests/unit_threaded/ut/mock.d:123 -        instead of the expected Tuple!(int, string)(5, "quux")`);
34     }
35 }
36 
37 @("mock interface negative test")
38 @safe pure unittest {
39     import unit_threaded.should;
40 
41     interface Foo {
42         int foo(int, string) @safe pure;
43     }
44 
45     auto m = mock!Foo;
46     m.expect!"foo";
47     m.verify.shouldThrowWithMessage("Expected nth 0 call to foo did not happen");
48 }
49 
50 // can't be in the unit test itself
51 private class Class {
52     abstract int foo(int, string) @safe pure;
53     final int timesTwo(int i) @safe pure nothrow const { return i * 2; }
54     int timesThree(int i) @safe pure nothrow const { return i * 3; }
55     int timesThreeMutable(int i) @safe pure nothrow { return i * 3; }
56 }
57 
58 @("mock class positive test")
59 @safe pure unittest {
60 
61     int fun(Class f) {
62         return 2 * f.foo(5, "foobar");
63     }
64 
65     auto m = mock!Class;
66     m.expect!"foo";
67     fun(m);
68 }
69 
70 
71 @("mock interface multiple calls")
72 @safe pure unittest {
73     interface Foo {
74         int foo(int, string) @safe pure;
75         int bar(int) @safe pure;
76     }
77 
78     void fun(Foo f) {
79         f.foo(3, "foo");
80         f.bar(5);
81         f.foo(4, "quux");
82     }
83 
84     auto m = mock!Foo;
85     m.expect!"foo"(3, "foo");
86     m.expect!"bar"(5);
87     m.expect!"foo"(4, "quux");
88     fun(m);
89     m.verify;
90 }
91 
92 @("mock struct negative")
93 @safe pure unittest {
94     import unit_threaded.asserts;
95 
96     auto m = mockStruct;
97     m.expect!"foobar";
98     assertExceptionMsg(m.verify,
99                        "    tests/unit_threaded/ut/mock.d:123 - Expected nth 0 call to foobar did not happen\n");
100 
101 }
102 
103 @("mock struct values negative")
104 @safe pure unittest {
105     import unit_threaded.asserts;
106 
107     void fun(T)(T t) {
108         t.foobar(2, "quux");
109     }
110 
111     auto m = mockStruct;
112     m.expect!"foobar"(3, "quux");
113     fun(m);
114     assertExceptionMsg(m.verify,
115                        "    tests/unit_threaded/ut/mock.d:123 - foobar was called with unexpected Tuple!(int, string)(2, \"quux\")\n" ~
116                        "    tests/unit_threaded/ut/mock.d:123 -           instead of the expected Tuple!(int, string)(3, \"quux\")");
117 }
118 
119 
120 @("const(ubyte)[] return type]")
121 @safe pure unittest {
122     interface Interface {
123         const(ubyte)[] fun();
124     }
125 
126     auto m = mock!Interface;
127 }
128 
129 @("safe pure nothrow")
130 @safe pure unittest {
131     interface Interface {
132         int twice(int i) @safe pure nothrow /*@nogc*/;
133     }
134     auto m = mock!Interface;
135 }
136 
137 @("issue 63")
138 @safe pure unittest {
139     import unit_threaded.should;
140 
141     interface InterfaceWithOverloads {
142         int func(int) @safe pure;
143         int func(string) @safe pure;
144     }
145     alias ov = Identity!(__traits(allMembers, InterfaceWithOverloads)[0]);
146     auto m = mock!InterfaceWithOverloads;
147     m.returnValue!(0, "func")(3); // int overload
148     m.returnValue!(1, "func")(7); // string overload
149     m.expect!"func"("foo");
150     m.func("foo").shouldEqual(7);
151     m.verify;
152 }
153 
154 private class FooException: Exception {
155     import std.exception: basicExceptionCtors;
156     mixin basicExceptionCtors;
157 }
158 
159 
160 @("throwStruct custom")
161 @safe pure unittest {
162     import unit_threaded.should: shouldThrow;
163 
164     auto m = throwStruct!FooException;
165     m.foo.shouldThrow!FooException;
166     m.bar(1, "foo").shouldThrow!FooException;
167 }
168 
169 
170 @("throwStruct return value type")
171 @safe pure unittest {
172     import unit_threaded.asserts;
173     import unit_threaded.should: UnitTestException;
174     auto m = throwStruct!(UnitTestException, int);
175     int i;
176     assertExceptionMsg(i = m.foo,
177                        "    tests/unit_threaded/ut/mock.d:123 - foo was called");
178     assertExceptionMsg(i = m.bar,
179                        "    tests/unit_threaded/ut/mock.d:123 - bar was called");
180 }
181 
182 @("issue 68")
183 @safe pure unittest {
184     import unit_threaded.should;
185 
186     int fun(Class f) {
187         // f.timesTwo is mocked to return 2, no matter what's passed in
188         return f.timesThreeMutable(2);
189     }
190 
191     auto m = mock!Class;
192     m.expect!"timesThreeMutable"(2);
193     m.returnValue!("timesThreeMutable")(42);
194     fun(m).shouldEqual(42);
195 }
196 
197 @("issue69")
198 unittest {
199     import unit_threaded.should;
200 
201     static interface InterfaceWithOverloadedFuncs {
202         string over();
203         string over(string str);
204     }
205 
206     static class ClassWithOverloadedFuncs {
207         string over() { return "oops"; }
208         string over(string str) { return "oopsie"; }
209     }
210 
211     auto iMock = mock!InterfaceWithOverloadedFuncs;
212     iMock.returnValue!(0, "over")("bar");
213     iMock.returnValue!(1, "over")("baz");
214     iMock.over.shouldEqual("bar");
215     iMock.over("zing").shouldEqual("baz");
216 
217     auto cMock = mock!ClassWithOverloadedFuncs;
218     cMock.returnValue!(0, "over")("bar");
219     cMock.returnValue!(1, "over")("baz");
220     cMock.over.shouldEqual("bar");
221     cMock.over("zing").shouldEqual("baz");
222 }