Announcement Announcement Module
Collapse
No announcement yet.
mock testing with spring managed beans Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • mock testing with spring managed beans

    Hi,

    we have decorated our Spring managed beans with advices via the org.springframework.aop.framework.autoproxy.BeanNa meAutoProxyCreator using beanNames, as in:

    <bean id="proxyCreator" class="org.springframework.aop.framework.autoproxy .BeanNameAutoProxyCreator">
    <property name="beanNames">
    <list>
    <value>*Bean</value>
    </list>
    </property>
    <property name="interceptorNames">
    <list>
    <value>MyAdvice</value>
    </list>
    </property>
    </bean>

    <bean id="myBean" class="MyBeanDefault" />

    so if I get "myBean" from the applicationContext the reference will be that of a proxy due to the decorating advice. For mock testing purposes what I'd like to do is get a reference to MyBeanDefault, ie without the proxy, from the applicationContext - any ideas, outside of re-declaring the bean with a different name?


    thanks

    drc

  • #2
    Some caffeine-induced ideas...

    That's the great thing about this forum - you learn about a new part of the framework every day!

    Anyway, one idea would be to use a separate bean definition file just for your test cases. This test-only file could either leave out the BeanNameAutoProxyCreator completely, or (if that wasn't feasible) change its "beanNames" property not to include the beans you didn't want proxied.

    Another idea is to change your existing bean definition file to read the names of the to-be-decorated beans from a system property. In production you would set this property to its current "*Bean" value, whereas in your tests you could set it to whatever you wanted.

    I've had another idea (on a roll, just had my coffee!). If your test case is application context aware (or can be made so), and if the advice is only applied at the time of getting the target bean (as opposed to when the app context loads), which may be enforceable via the lazy-init parameter, then your test case could (1) set the proxy creator's "beanNames" not to include "myBean", then (2) get "myBean", which would therefore not be proxied, then (3) set the proxy creator's "beanNames" back to its normal value.

    All of the above begs the question of what you mean by "mock" though. You didn't explain exactly what you want to mock, but if you want to mock "myBean", why not use EasyMock or a similar mock-generating tool?

    Comment


    • #3
      We want to mock out (using jmock) the collaborators of our spring managed beans, so MyBean is the class that will have its collaborators mocked out, ie dao's etc. Given that our advices open/close transactions & do other things I dont want these to be part of the mock test - hence I only want the MyBean instance returned from the spring factory without the proxys. So the test case is application context aware.

      As for some of your suggestions:
      - I could redefine myBean in applicationContext*.xml - but then I'd have to maintain this definition as well - so this isnt an option
      - The system properties - not really sure how this would work
      - I'II look into the idea of lazy-init & changing the proxy-creators beans to not include *Bean


      Go Sydney Swans...


      drc

      Comment


      • #4
        Hi drc

        For unit testing, why not just use a plain vanilla JUnit test in conjunction with JMock? You can totally leave out the Spring container in that case; this is certainly the approach that I and a number of the other Spring dev team use. To wit...

        Code:
        public final class FooTests extends TestCase {
        
            public void testBar() {
                Foo foo = new Foo();
                
                // inject JMock-based collaborators into the Foo instance
                
                // test!
            }
        
            public void testBaz() {
                Foo foo = new Foo();
                
                // inject JMock-based collaborators into the Foo instance
                
                // test!
            }
        }
        Cheers
        Rick

        Comment


        • #5
          +1

          I was just about to ask drc the same thing!

          Comment


          • #6
            Rick & Andews,

            the reason why I want to use the spring container in the test is that getting the beans from the spring container will result in all of the collaborators being injected into the spring managed bean. There are a couple of benefits I see to this, rather doing a new on the bean as suggested:
            1) I dont have to new all of the collaborators and then physically inject them into the bean in the test
            2) when the bean under test changes, eg a new collaborator, then I dont have to go back to my test and inject it in, as Spring will have already injected it in for me

            So I think it results in a bit less code in the test and a bit less maintenance over time.

            let me know what u think?

            thanks.

            Comment


            • #7
              In this case you'll have to use either a different proxying technique (so you'll end up with two beans definitions - one of the original bean and one of the proxied bean) or you can set exposeProxy to true on BeanNameAutoProxyCreator.
              See the javadoc for ProxyConfig for more info.

              Comment

              Working...
              X