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 }