digitalmars.D - Monkey Patching in D
- Peter Lundgren (15/15) Jun 04 2013 I'm interested in trying to write a monkey patching* library in
- Jonathan M Davis (5/23) Jun 04 2013 If you haven't watched it yet, you should watch this talk from dconf. It...
- Peter Lundgren (2/7) Jun 04 2013 Yeah, deject looks pretty nice, but only works on code you own.
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (5/7) Jun 04 2013 The maintainer has just announced that it is up to date with the recent
- Jacob Carlborg (16/29) Jun 05 2013 I would suggestion using some kind of wrapper instead of doing true
- Peter Lundgren (8/21) Jun 05 2013 That's a reasonable option too. I think I'd rather use deject.
- QAston (12/36) Jun 05 2013 Making mocks work with statical world of D could definitely be
- Paulo Pinto (7/31) Jun 06 2013 The solution would be to use tools like in C++/Java/.NET world
- Peter Lundgren (4/10) Jun 06 2013 I came to the same conclusion, so that's exactly what I'm
- Jacob Carlborg (6/9) Jun 09 2013 Have a look at this old D1 library:
- Dicebot (9/14) Jun 07 2013 As I have mentioned in reddit comment to that presentation, you
I'm interested in trying to write a monkey patching* library in D. Specifically, aiming to support mocks and stubs for unit testing. I have a couple of questions: 1) What prior art is there here? I am aware of DMocks (does this project still need a maintainer?). 2) How crazy am I for even thinking this is a good idea? Are there any obviously better alternatives. * I'm not sure if there is well defined terminology here (especially applying these ideas to compiled languages). To clarify, when I say monkey patch, I mean to intercept a function or method call at run-time. I believe, in the case of D, this would require self modifying code using techniques like those used here: http://www.yosefk.com/blog/machine-code-monkey-patching.html
Jun 04 2013
On Wednesday, June 05, 2013 04:18:34 Peter Lundgren wrote:I'm interested in trying to write a monkey patching* library in D. Specifically, aiming to support mocks and stubs for unit testing. I have a couple of questions: 1) What prior art is there here? I am aware of DMocks (does this project still need a maintainer?). 2) How crazy am I for even thinking this is a good idea? Are there any obviously better alternatives. * I'm not sure if there is well defined terminology here (especially applying these ideas to compiled languages). To clarify, when I say monkey patch, I mean to intercept a function or method call at run-time. I believe, in the case of D, this would require self modifying code using techniques like those used here: http://www.yosefk.com/blog/machine-code-monkey-patching.htmlIf you haven't watched it yet, you should watch this talk from dconf. It's specifically about stuff like mock testing in D. http://www.youtube.com/watch?v=V98Z11V7kEY - Jonathan M Davis
Jun 04 2013
If you haven't watched it yet, you should watch this talk from dconf. It's specifically about stuff like mock testing in D. http://www.youtube.com/watch?v=V98Z11V7kEY - Jonathan M DavisYeah, deject looks pretty nice, but only works on code you own. It's certainly a much safer alternative to what I'm considering.
Jun 04 2013
On 06/04/2013 07:18 PM, Peter Lundgren wrote:I am aware of DMocks (does this project still need a maintainer?).The maintainer has just announced that it is up to date with the recent compiler: http://forum.dlang.org/post/dnvfxgvecmskjofjryfj forum.dlang.org Ali
Jun 04 2013
On 2013-06-05 04:18, Peter Lundgren wrote:I'm interested in trying to write a monkey patching* library in D. Specifically, aiming to support mocks and stubs for unit testing. I have a couple of questions: 1) What prior art is there here? I am aware of DMocks (does this project still need a maintainer?). 2) How crazy am I for even thinking this is a good idea? Are there any obviously better alternatives. * I'm not sure if there is well defined terminology here (especially applying these ideas to compiled languages). To clarify, when I say monkey patch, I mean to intercept a function or method call at run-time. I believe, in the case of D, this would require self modifying code using techniques like those used here: http://www.yosefk.com/blog/machine-code-monkey-patching.htmlI would suggestion using some kind of wrapper instead of doing true monkey patching. Example: class Wrapper { private Object o; this (Object o) { this.o = o; } auto opDispatch (string name, Args ...) (Args args) { // Use this function to "catch" all calls and forward as necessary to "o" } } http://dlang.org/operatoroverloading.html#Dispatch -- /Jacob Carlborg
Jun 05 2013
On Wednesday, 5 June 2013 at 07:17:50 UTC, Jacob Carlborg wrote:I would suggestion using some kind of wrapper instead of doing true monkey patching. Example: class Wrapper { private Object o; this (Object o) { this.o = o; } auto opDispatch (string name, Args ...) (Args args) { // Use this function to "catch" all calls and forward as necessary to "o" } } http://dlang.org/operatoroverloading.html#DispatchThat's a reasonable option too. I think I'd rather use deject. The problem I'm trying to solve (and maybe this isn't as important as I think) is that DMocks or deject + DMocks only works on a subset of the language. I can't mock out free function calls, private or final methods, or functions on structs or unions (can I inject mocked structs using deject?). What do I do when I want to mock out std.stdio or std.random?
Jun 05 2013
On Wednesday, 5 June 2013 at 13:19:33 UTC, Peter Lundgren wrote:On Wednesday, 5 June 2013 at 07:17:50 UTC, Jacob Carlborg wrote:Making mocks work with statical world of D could definitely be done - the language has many useful tools like alias or mixins to do that. I think that substitution here may be a problem. It'd probably be required to use aliases instead of bare types in user code, so types could be fully substituted. Mocking statically linked methods is a similar problem - consider: MyType a = new Mocker().mock!(MyType ); a.finalMethod() will call MyType.finalMethod, not Mock!MyType.finalMethod. Using aliases for defining types is a sollution but it requires changes to user code. Maybe deject has a sollution to this problem.I would suggestion using some kind of wrapper instead of doing true monkey patching. Example: class Wrapper { private Object o; this (Object o) { this.o = o; } auto opDispatch (string name, Args ...) (Args args) { // Use this function to "catch" all calls and forward as necessary to "o" } } http://dlang.org/operatoroverloading.html#DispatchThat's a reasonable option too. I think I'd rather use deject. The problem I'm trying to solve (and maybe this isn't as important as I think) is that DMocks or deject + DMocks only works on a subset of the language. I can't mock out free function calls, private or final methods, or functions on structs or unions (can I inject mocked structs using deject?). What do I do when I want to mock out std.stdio or std.random?
Jun 05 2013
On Wednesday, 5 June 2013 at 13:19:33 UTC, Peter Lundgren wrote:On Wednesday, 5 June 2013 at 07:17:50 UTC, Jacob Carlborg wrote:The solution would be to use tools like in C++/Java/.NET world that rewrite assembly/bytecode and replace method/function calls with your mocks. It works most of the time. -- PauloI would suggestion using some kind of wrapper instead of doing true monkey patching. Example: class Wrapper { private Object o; this (Object o) { this.o = o; } auto opDispatch (string name, Args ...) (Args args) { // Use this function to "catch" all calls and forward as necessary to "o" } } http://dlang.org/operatoroverloading.html#DispatchThat's a reasonable option too. I think I'd rather use deject. The problem I'm trying to solve (and maybe this isn't as important as I think) is that DMocks or deject + DMocks only works on a subset of the language. I can't mock out free function calls, private or final methods, or functions on structs or unions (can I inject mocked structs using deject?). What do I do when I want to mock out std.stdio or std.random?
Jun 06 2013
On Thursday, 6 June 2013 at 07:46:13 UTC, Paulo Pinto wrote:The solution would be to use tools like in C++/Java/.NET world that rewrite assembly/bytecode and replace method/function calls with your mocks. It works most of the time. -- PauloI came to the same conclusion, so that's exactly what I'm proposing / asking for feedback on. Do you think that it would be reasonable to apply those techniques to D?
Jun 06 2013
On 2013-06-06 14:53, Peter Lundgren wrote:I came to the same conclusion, so that's exactly what I'm proposing / asking for feedback on. Do you think that it would be reasonable to apply those techniques to D?Have a look at this old D1 library: http://flectioned.kuehne.cn/ It allows you to redirect a function. -- /Jacob Carlborg
Jun 09 2013
On Wednesday, 5 June 2013 at 13:19:33 UTC, Peter Lundgren wrote:The problem I'm trying to solve (and maybe this isn't as important as I think) is that DMocks or deject + DMocks only works on a subset of the language. I can't mock out free function calls, private or final methods, or functions on structs or unions (can I inject mocked structs using deject?).As I have mentioned in reddit comment to that presentation, you kind of can achieve same dependency substitution by generating whole mock modules and changing root import path via flag for test run. As module is minimal D unit of encapsulation, that is even more natural. However, I don't know if it is possible to somehow get dependency list automatically in such model. Probably by grep'ing linker errors and doing demangling?
Jun 07 2013