Details

    • Type: Wish Wish
    • Status: Open Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: None
    • Fix Version/s: None
    • Component/s: Java Integration
    • Labels:
      None
    • Testcase included:
      yes
    • Number of attachments :
      1

      Description

      I was told to post this as a jira issue as well: This post introduces a duck-typing extension for JRuby, extending the possibilities for duck-typing involving java classes. A working prototype is ready for download. Request for comments.

      Hi all,

      When testing java code (jruby, rspec), I frequently want to test code that takes some argument that I want to mock. If the code looks like this

      public void method1(ISomeInterface param)

      { ... }

      everything is fine. If it looks like this

      public void method2(AClassThatIsReallyHeavyToConstruct param) { ... }

      I am in trouble. JRuby doesn't allow me to cloak my ruby classes as java classes (duck-typing), only as java interfaces. Sometimes you can inherit from the class that you want to mock, but as hinted at by the example, this class is really to fat to construct and let's assume that I can't.

      So I hacked together a small prototype [3] that allows me to do exactly that, using code I've found in jMock 2. The code allows you to

      ruby_mock = flexmock(:some_mock) # or whatever
      java_mock = DuckType::INSTANCE.transmogrify(ruby_mock,
      AClassThatIsReallyHeavyToConstruct.java_class)

      yielding a java class instance that looks exactly like a descendant of AClassThatIsReallyHeavyToConstruct to the JVM, except that it's not. The instance that you get is a proxy class instance that forwards all calls to the ruby_mock object.

      This obviously solves my problem and I can continue to test. But it is a kludge; I would really like JRuby to do all this work for me. How about merging this into JRuby? [1] This looks like a nice addition for the java integration to me. [2]

      I don't know the JRuby code base well enough to integrate this on my own. I am working on it though - and perhaps someone might be willing to help me with this?

      kaspar

      [1] Please disregard the bad state of the java code involved. Especially that singleton-pattern is probably out of place. But I hope that you can look at the essence and not at the form. (Which would have to be changed in case of a JRuby integration)

      [2] As far as possible, I've made sure that the original authors are credited. I took the jMock ClassImpostorizer and special-purposed it. I am also in contact with the author of the code - he is ok with this new use.

      [3] You can fetch the code from http://absurd.li/system/posts/impostor.tgz. You'll need rspec and possibly some other common stuff installed to be able to run the specs. If you use this for your own projects, don't forget to include the .jars in the ./lib dir.

      1. impostor.tgz
        4.13 MB
        Kaspar Schiess

        Activity

        Hide
        Charles Oliver Nutter added a comment -

        This has gotten pretty old, but seems a little too invasive to include as part of JRuby proper to me. Couldn't this be implemented as an add-on library that allows mocking of Java classes? Also, perhaps there's something in jtestr (for example) that already does this?

        Show
        Charles Oliver Nutter added a comment - This has gotten pretty old, but seems a little too invasive to include as part of JRuby proper to me. Couldn't this be implemented as an add-on library that allows mocking of Java classes? Also, perhaps there's something in jtestr (for example) that already does this?
        Hide
        Kaspar Schiess added a comment -

        Thank you for your reply.

        Just had another look at jtestr. While it does extend mocha to come part of the way towards this extension, it doesn't go all the way. Looks like the issues I've ran into are tied to the bad code I was trying to test.

        This could be part of jtestr - although I don't like the way this package is bundled from a rubyist perspective. I will be trying to argue why this should be part of jruby:

        What should the java integration be: Ruby approaching Java living by Java's rules? Or Java bent to Ruby's rules? More concretly, should Ruby classes duck-type even when passed to java code? Or should you have to derive from the proper superclasses like Java demands you to? I find the 'subclassing-to-enter-lineage'-style of code to be quite unnatural to Ruby (where you would do a 'define-all-methods-to-enter-lineage').

        I can live with the reasons you give for rejecting this, namely it being invasive and probably not in line with what you're trying to achieve. I won't be submitting this to jtestr though - I just can't get myself to want to help there. The link will stay active and this ticket will probably help someone having the same problem.

        kaspar

        Show
        Kaspar Schiess added a comment - Thank you for your reply. Just had another look at jtestr. While it does extend mocha to come part of the way towards this extension, it doesn't go all the way. Looks like the issues I've ran into are tied to the bad code I was trying to test. This could be part of jtestr - although I don't like the way this package is bundled from a rubyist perspective. I will be trying to argue why this should be part of jruby: What should the java integration be: Ruby approaching Java living by Java's rules? Or Java bent to Ruby's rules? More concretly, should Ruby classes duck-type even when passed to java code? Or should you have to derive from the proper superclasses like Java demands you to? I find the 'subclassing-to-enter-lineage'-style of code to be quite unnatural to Ruby (where you would do a 'define-all-methods-to-enter-lineage'). I can live with the reasons you give for rejecting this, namely it being invasive and probably not in line with what you're trying to achieve. I won't be submitting this to jtestr though - I just can't get myself to want to help there. The link will stay active and this ticket will probably help someone having the same problem. kaspar
        Hide
        Charles Oliver Nutter added a comment -

        Well, your changes have not been rejected yet

        I can appreciate what you're saying about making Ruby and Java meet somewhere in the middle. It would be great, truly, if we could have this sort of magic just work for all cases. And I suppose the reason I say it seems a little too invasive is because it feels like something you'd want in a library. Most people won't need this for typical applications. But I am interested in working with you to build off this...

        I have not yet looked at your code. But we need more people that can hack bytecode this way to help us improve JRuby's ability to extend other classes. Would you be interested in helping there? If you are able to help with that, maybe we can come up with a unified way to support class extension and concrete class duck-typing. I would be more comfortable with it then

        Show
        Charles Oliver Nutter added a comment - Well, your changes have not been rejected yet I can appreciate what you're saying about making Ruby and Java meet somewhere in the middle. It would be great, truly, if we could have this sort of magic just work for all cases. And I suppose the reason I say it seems a little too invasive is because it feels like something you'd want in a library. Most people won't need this for typical applications. But I am interested in working with you to build off this... I have not yet looked at your code. But we need more people that can hack bytecode this way to help us improve JRuby's ability to extend other classes. Would you be interested in helping there? If you are able to help with that, maybe we can come up with a unified way to support class extension and concrete class duck-typing. I would be more comfortable with it then
        Hide
        Kaspar Schiess added a comment -

        I agree completely with you, this can be an add-on without loosing any power. And considering the invasive nature of the code involved, I myself would like to be able to swap that out for A/B testing .

        Of course I would like to help with JRuby. Last time I looked, I just didn't seem to be able to get started. If you are interested in coming some of the way by providing me an interface I program against, I will be happy to formulate as a patch what I've posted here as a prototype.

        regards,
        kaspar

        Show
        Kaspar Schiess added a comment - I agree completely with you, this can be an add-on without loosing any power. And considering the invasive nature of the code involved, I myself would like to be able to swap that out for A/B testing . Of course I would like to help with JRuby. Last time I looked, I just didn't seem to be able to get started. If you are interested in coming some of the way by providing me an interface I program against, I will be happy to formulate as a patch what I've posted here as a prototype. regards, kaspar

          People

          • Assignee:
            Unassigned
            Reporter:
            Kaspar Schiess
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated: