How can I change out value in callback using Moq? -
i'm trying mock 3rd party lib in unittest. puts result data in out parameter while returns bool signaling if more data available. want test component behaves when there 2 pages of data can't figure out how change data in out parameter in setup() method. created minimalist sample can run in linqpad:
void main() { var m = new mock<ifoo>(); string s = "1"; var pg = 0; m.setup(o => o.query(out s)) .returns(() => pg==0) .callback(() => { pg++; s = "2"; }); ifoo f = m.object; string z; while (f.query(out z)) { z.dump(); } z.dump(); } public interface ifoo { bool query(out string result); } the output is
1 1 how can it?
it looks changing of out parameters not supported out of box. best solution found far based on hack - see https://stackoverflow.com/a/19598345/463041. invokes private method using reflection. using hack, working solution this:
void main() { var m = new mock<ifoo>(); string s = "1"; var pg = 0; m.setup(p => p.query(out s)) .outcallback((out string v) => v = pg==0 ? "1" : "2") .returns(() => pg==0) .callback(() => { pg++; s = "2"; }); ifoo f = m.object; string z; while (f.query(out z)) { z.dump(); } z.dump(); } public interface ifoo { bool query(out string result); } public static class moqextensions { public delegate void outaction<tout>(out tout outval); public delegate void outaction<in t1,tout>(t1 arg1, out tout outval); public static ireturnsthrows<tmock, treturn> outcallback<tmock, treturn, tout>(this icallback<tmock, treturn> mock, outaction<tout> action) tmock : class { return outcallbackinternal(mock, action); } public static ireturnsthrows<tmock, treturn> outcallback<tmock, treturn, t1, tout>(this icallback<tmock, treturn> mock, outaction<t1, tout> action) tmock : class { return outcallbackinternal(mock, action); } private static ireturnsthrows<tmock, treturn> outcallbackinternal<tmock, treturn>(icallback<tmock, treturn> mock, object action) tmock : class { mock.gettype() .assembly.gettype("moq.methodcall") .invokemember("setcallbackwitharguments", bindingflags.invokemethod | bindingflags.nonpublic | bindingflags.instance, null, mock, new[] { action }); return mock ireturnsthrows<tmock, treturn>; } }
Comments
Post a Comment