1 module mocked.tests.expectations; 2 3 import dshould; 4 import dshould.ShouldType; 5 import mocked; 6 import unit_threaded : ShouldFail; 7 8 void startWith(Should, T)(Should should, T expected, 9 Fence _ = Fence(), string file = __FILE__, size_t line = __LINE__) 10 if (isInstanceOf!(ShouldType, Should)) 11 { 12 auto got = should.got; 13 should.check(got.startsWith(expected), expected, got, file, line); 14 } 15 16 @ShouldFail("if an expected method hasn't been called") 17 unittest 18 { 19 static class Dependency 20 { 21 string say(string phrase) 22 { 23 return phrase; 24 } 25 } 26 with (Mocker()) 27 { 28 auto dependency = mock!Dependency; 29 30 dependency.expect.say("Man geht zu Grunde,") 31 .returns("wenn man immer zu den Gründen geht."); 32 } 33 } 34 35 @("repeats expectations infinitely") 36 unittest 37 { 38 enum expected = "Piscis primum a capite foetat"; 39 40 Mocker mocker; 41 42 auto mock = mocker.mock!Object; 43 44 mock.expect.toString().returns(expected).repeatAny; 45 46 Object object = mock.get; 47 48 object.toString.should.equal(expected); 49 object.toString.should.equal(expected); 50 51 mocker.verify; 52 } 53 54 @("prints arguments in the unexpected call error message") 55 unittest 56 { 57 static class Dependency 58 { 59 void say(string phrase1, string phrase2) 60 { 61 } 62 } 63 Mocker mocker; 64 65 auto mock = mocker.mock!Dependency.get; 66 67 mock.say("Ton der Jugend", "zu laut.") 68 .should.throwAn!UnexpectedCallError 69 .where.msg.should.be(`Unexpected call: Dependency.say("Ton der Jugend", "zu laut.")`); 70 } 71 72 @("throws once") 73 unittest 74 { 75 static class Dependency 76 { 77 void say(string phrase) 78 { 79 } 80 } 81 Mocker mocker; 82 83 auto mock = mocker.mock!Dependency; 84 85 mock.expect.say("Die Ängstlichkeit vergiftet die Seele.").repeat(2); 86 87 mocker.verify.should.throwAn!ExpectationViolationException; 88 mocker.verify.should.not.throwAn!ExpectationViolationException; 89 } 90 91 @("gives multiline error messages on mismatched arguments") 92 unittest 93 { 94 static class Dependency 95 { 96 void say(string phrase) 97 { 98 } 99 } 100 Mocker mocker; 101 102 auto mock = mocker.mock!Dependency; 103 104 mock.expect.say("Let's eat, grandma!").repeat(2); 105 106 mock.say("Let's eat grandma!") 107 .should.throwAn!UnexpectedArgumentError 108 .where.msg.should.be("Expectation failure: 109 Expected: Dependency.say(\"Let's eat, grandma!\") 110 but got: Dependency.say(\"Let's eat grandma!\")"); 111 } 112 113 @("verify prints what method was expected") 114 unittest 115 { 116 enum string phrase = "Täglich erstaune ich: ich kenne mich selber nicht!"; 117 static class Dependency 118 { 119 void say(string) 120 { 121 } 122 } 123 Mocker mocker; 124 125 auto mock = mocker.mock!Dependency; 126 127 mock.expect.say(phrase); 128 129 mocker.verify 130 .should.throwAn!ExpectationViolationException 131 .where.msg.should.be(`Expected method not called: Dependency.say("` ~ phrase ~ `")`); 132 } 133 134 @("verify prints what method was expected for ints") 135 unittest 136 { 137 static class Dependency 138 { 139 void say(int) 140 { 141 } 142 } 143 Mocker mocker; 144 145 auto mock = mocker.mock!Dependency; 146 147 mock.expect.say(5); 148 149 mocker.verify 150 .should.throwAn!ExpectationViolationException 151 .where.msg.should.be(`Expected method not called: Dependency.say(5)`); 152 } 153 154 @("allows to pick the overload without specifying the arguments") 155 unittest 156 { 157 enum string expected = "ad nullius rei essentiam pertinet existentia"; 158 static class Dependency 159 { 160 string show(bool x) 161 { 162 return x ? "true" : "false"; 163 } 164 165 string show(string x) 166 { 167 return x; 168 } 169 } 170 Mocker mocker; 171 172 auto mock = mocker.mock!Dependency; 173 174 mock.expect.show!string.returns(expected); 175 176 auto dependency = mock.get; 177 178 dependency.show(null).should.equal(expected); 179 } 180 181 @("allows to pick the overload without specifying the arguments") 182 unittest 183 { 184 static class Dependency 185 { 186 void show(string, string) 187 { 188 } 189 } 190 Mocker mocker; 191 auto mock = mocker.mock!Dependency; 192 193 static assert(!is(typeof(mock.expect.show!string))); 194 } 195 196 @("skips private overloads") 197 unittest 198 { 199 static class Dependency 200 { 201 void handle(string) 202 { 203 } 204 205 private void handle(int) 206 { 207 } 208 } 209 Mocker mocker; 210 static assert(is(typeof(mocker.mock!Dependency()))); 211 } 212 213 @("picks public overload") 214 unittest 215 { 216 static class Dependency 217 { 218 private void handle(int) 219 { 220 } 221 222 void handle(string) 223 { 224 } 225 } 226 Mocker mocker; 227 auto builder = mocker.mock!Dependency(); 228 229 builder.expect.handle("In vino veritas"); 230 231 builder.get.handle("In vino veritas"); 232 } 233 234 @("lets .repeatAny() do a forward lookup") 235 unittest 236 { 237 static class Dependency 238 { 239 string finishQuote(string phrase) 240 { 241 return phrase; 242 } 243 } 244 Mocker mocker; 245 auto mock = mocker.mock!Dependency; 246 247 mock.expect 248 .finishQuote("Ducunt volentem fata,") 249 .returns("nolentem trahunt") 250 .repeatAny; 251 mock.expect.finishQuote("Seneca").returns("epistulae"); 252 253 mock.get.finishQuote("Seneca").should.equal("epistulae"); 254 } 255 256 @ShouldFail("if functions are called not in the given order") 257 unittest 258 { 259 static class Dependency 260 { 261 void callFirst() 262 { 263 } 264 265 void callSecond() 266 { 267 } 268 } 269 Mocker mocker; 270 auto mock = mocker.mock!Dependency; 271 272 mock.expect.callFirst; 273 mock.expect.callSecond; 274 275 mock.get.callSecond; 276 mock.get.callFirst; 277 } 278 279 @("supports const method") 280 unittest 281 { 282 static class Dependency 283 { 284 void act() const 285 { 286 } 287 } 288 Mocker mocker; 289 auto builder = mocker.mock!Dependency(); 290 291 builder.expect.act; 292 293 builder.act; 294 } 295 296 @("works with Nullables") 297 unittest 298 { 299 import std.typecons : Nullable, nullable; 300 301 static class Dependency 302 { 303 void say(Nullable!string phrase) 304 { 305 } 306 } 307 with (Mocker()) 308 { 309 auto dependency = mock!Dependency; 310 auto expected = nullable("procul, o procul..."); 311 312 dependency.expect.say(nullable("procul, o procul...")); 313 314 dependency.say(Nullable!string()) 315 .should.throwAn!UnexpectedArgumentError; 316 } 317 } 318 319 @("allows functions to be called not in the given order") 320 unittest 321 { 322 static class Dependency 323 { 324 void callFirst(int) 325 { 326 } 327 } 328 Mocker mocker; 329 auto mock = mocker.mock!Dependency.unordered; 330 331 mock.expect.callFirst(1); 332 mock.expect.callFirst(2); 333 334 mock.get.callFirst(2); 335 mock.get.callFirst(1); 336 }