1 module mocked.tests.mocking;
2 
3 import dshould;
4 import mocked;
5 import std.typecons;
6 
7 @("mocks functions with one argument")
8 unittest
9 {
10     static class Dependency
11     {
12         string call(string phrase)
13         {
14             return phrase;
15         }
16     }
17     with (Mocker())
18     {
19         auto dependency = mock!Dependency;
20 
21         dependency.expect.call("Noch ein Jahrhundert Zeitungen")
22             .returns("und alle Worte stinken");
23 
24         dependency.call("Noch ein Jahrhundert Zeitungen").should
25             .equal("und alle Worte stinken");
26     }
27 }
28 
29 @("mocks functions without arguments")
30 unittest
31 {
32     enum int expected = 10;
33 
34     with (Mocker())
35     {
36         auto dependency = mock!Object;
37 
38         dependency.expect.toHash.returns(expected);
39 
40         dependency.toHash.should.equal(expected);
41     }
42 }
43 
44 @("mocks overloaded functions")
45 unittest
46 {
47     static class Dependency
48     {
49         int call(int number)
50         {
51             return number;
52         }
53 
54         string call(string phrase)
55         {
56             return phrase;
57         }
58     }
59     with (Mocker())
60     {
61         auto dependency = mock!Dependency;
62 
63         dependency.expect.call("Die beste Maske, die wir tragen")
64             .returns("ist unser eigenes Gesicht");
65 
66         dependency.call("Die beste Maske, die wir tragen").should
67             .equal("ist unser eigenes Gesicht");
68     }
69 }
70 
71 @("mocks overloaded functions with the same return type")
72 unittest
73 {
74     static class Dependency
75     {
76         string call(char character)
77         {
78             return [character];
79         }
80 
81         string call(string phrase)
82         {
83             return phrase;
84         }
85     }
86     with (Mocker())
87     {
88         auto dependency = mock!Dependency;
89 
90         dependency.expect.call("Wenn dein Werk den Mund aufthut")
91             .returns("sollst du selber das Maul halten");
92 
93         dependency.call("Wenn dein Werk den Mund aufthut").should
94             .equal("sollst du selber das Maul halten");
95     }
96 }
97 
98 @("keeps original behavior")
99 unittest
100 {
101     static class Dependency
102     {
103         string identity(string phrase)
104         {
105             return phrase;
106         }
107     }
108     with (Mocker())
109     {
110         auto dependency = mock!Dependency;
111 
112         dependency.expect.identity("Jedes Wort ist ein Vorurtheil.")
113             .passThrough;
114 
115         dependency.identity("Jedes Wort ist ein Vorurtheil.").should
116             .equal("Jedes Wort ist ein Vorurtheil.");
117     }
118 }
119 
120 @("ignores arguments")
121 unittest
122 {
123     static class Dependency
124     {
125         string identity(string phrase)
126         {
127             return phrase;
128         }
129     }
130     with (Mocker())
131     {
132         auto dependency = mock!Dependency;
133 
134         dependency.expect.identity.returns("die nicht durch das Glas kann");
135 
136         dependency.identity("Die Fliege").should
137             .equal("die nicht durch das Glas kann");
138     }
139 }
140 
141 @("ignores final functions")
142 unittest
143 {
144     static class Dependency
145     {
146         final string say(string)
147         {
148             return "Die Alten lasen laut.";
149         }
150     }
151     with (Mocker())
152     {
153         auto dependency = mock!Dependency;
154 
155         dependency.say(null).should.equal("Die Alten lasen laut.");
156     }
157 }
158 
159 @("mocks functions with two arguments")
160 unittest
161 {
162     static class Dependency
163     {
164         string say(string, string)
165         {
166             return null;
167         }
168     }
169     with (Mocker())
170     {
171         auto dependency = mock!Dependency;
172 
173         dependency.expect.say("Derselbe Text", "erlaubt unzählige Auslegungen:")
174             .returns(q{es giebt keine "richtige" Auslegung..});
175 
176         dependency.say("Derselbe Text", "erlaubt unzählige Auslegungen:").should
177             .equal(q{es giebt keine "richtige" Auslegung..});
178     }
179 }
180 
181 @("checks consecutive calls")
182 unittest
183 {
184     static class Dependency
185     {
186         string say(string phrase)
187         {
188             return phrase;
189         }
190     }
191     with (Mocker())
192     {
193         auto dependency = mock!Dependency;
194 
195         dependency.expect.say(q{Die "wahre Welt",})
196             .returns("wie immer auch man sie bisher concipirt hat, -");
197 
198         dependency.expect.say("sie war immer")
199             .returns("die scheinbare Welt noch einmal.");
200 
201         dependency.say(q{Die "wahre Welt",}).should
202             .equal("wie immer auch man sie bisher concipirt hat, -");
203 
204         dependency.say("sie war immer").should
205             .equal("die scheinbare Welt noch einmal.");
206     }
207 }
208 
209 @("mocks classes with constructors")
210 unittest
211 {
212     static class Dependency
213     {
214         string phrase;
215 
216         public this(string phrase)
217         {
218             this.phrase = phrase;
219         }
220 
221         public string saySomething()
222         {
223             return this.phrase;
224         }
225     }
226     with (Mocker())
227     {
228         auto dependency = mock!Dependency("Alea iacta est.");
229 
230         dependency.expect.saySomething().passThrough;
231 
232         dependency.saySomething().should.equal("Alea iacta est.");
233     }
234 }
235 
236 @("mocks void functions")
237 unittest
238 {
239     static class Dependency
240     {
241         void method()
242         {
243         }
244     }
245     static assert(is(typeof(Mocker().mock!Dependency())));
246 }
247 
248 @("mocks classes with overloaded constructors")
249 unittest
250 {
251     import std.string : join, outdent, strip;
252 
253     static class Dependency
254     {
255         string phrase;
256 
257         public this(string phrase)
258         {
259             this.phrase = phrase;
260         }
261 
262         public this(string part1, string part2)
263         {
264             this.phrase = [part1, part2].join('\n');
265         }
266 
267         public string say()
268         {
269             return this.phrase;
270         }
271     }
272     with (Mocker())
273     {
274         auto dependency = mock!Dependency("Kaum seid ihr geboren,",
275                 "so fangt ihr auch schon an zu sterben.");
276 
277         dependency.expect.say().passThrough;
278 
279         dependency.say.should.equal(r"
280                 Kaum seid ihr geboren,
281                 so fangt ihr auch schon an zu sterben.
282                 ".outdent.strip);
283     }
284 }
285 
286 @("allows to disable the constructor")
287 unittest
288 {
289     static class Dependency
290     {
291         public this(string)
292         {
293         }
294     }
295     static assert(is(typeof(Mocker().mock!Dependency())));
296 }
297 
298 @("allows arbitrary actions")
299 unittest
300 {
301     enum string expected = "Nihil est in intellectu, quod non prius fuerit in sensibus";
302     static class Dependency
303     {
304         void setPhrase()
305         {
306         }
307     }
308 
309     string phrase;
310     Mocker mocker;
311     auto dependency = mocker.mock!Dependency();
312 
313     dependency.expect.setPhrase().action(() {
314         phrase = expected;
315     });
316 
317     dependency.setPhrase();
318 
319     phrase.should.equal(expected);
320 }
321 
322 @("propagates the value returned by an action")
323 unittest
324 {
325     enum string expected = "Auf seine Fehler säen.";
326     static class Dependency
327     {
328         string phrase()
329         {
330             return null;
331         }
332     }
333 
334     Mocker mocker;
335     auto dependency = mocker.mock!Dependency;
336 
337     dependency.expect.phrase().action(() => expected);
338 
339     dependency.phrase.should.equal(expected);
340 }
341 
342 @(".action inherits nothrow from the mocked method")
343 unittest
344 {
345     static class Dependency
346     {
347         void act() pure @safe
348         {
349         }
350     }
351     alias action = () pure @safe {
352         throw new Exception("Von sich absehen ist nöthig um gut - zu sehen.");
353     };
354     Mocker mocker;
355     auto dependency = mocker.mock!Dependency;
356 
357     static assert(is(typeof(dependency.expect.act().action(action))));
358 }
359 
360 @("arguments can be const objects")
361 unittest
362 {
363     interface A
364     {
365         void func(const Object);
366     }
367     Mocker mocker;
368 
369     mocker.mock!A();
370 }
371 
372 @("supports struct with immutable members as arguments")
373 unittest
374 {
375     static struct S
376     {
377         private immutable string s;
378     }
379     static class Dependency
380     {
381         void withDefaultParameter(S)
382         {
383         }
384     }
385    static assert(is(typeof(Mocker().mock!Dependency())));
386 }
387 
388 @("supports default parameters")
389 unittest
390 {
391     enum string expected = "simplex sigillum veri";
392 
393     static class Dependency
394     {
395         void say(string = expected)
396         {
397         }
398     }
399     Mocker mocker;
400 
401     auto mocked = mocker.mock!Dependency;
402 
403     mocked.expect.say();
404 
405     mocked.say(expected);
406 }
407 
408 @("can mock functions with more than 2 parameters")
409 unittest
410 {
411     static class Dependency
412     {
413         void say(string, string, string)
414         {
415         }
416     }
417     Mocker mocker;
418     static assert(is(typeof(mocker.mock!Dependency())));
419 }