Mocking a class loaded from its FQCN

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Mocking a class loaded from its FQCN

KARR, DAVID
I'm trying to write an integration test for a Gradle plugin, using nebula-test.

The plugin provides the ability to specify a fully-qualified class name in an extension block, which the plugin's task then loads (using "Class.forName()") and instantiates to do work.  I could refactor the plugin so that I could inject a mock instance of that class into the code under test, but I'd like to see if it's possible to mock a class and then provide that class name to the plugin and let it load that class (which would already be loaded).

When I run the test, however, my plugin code fails with an error like this:

        java.lang.ClassNotFoundException: com.sun.proxy.$Proxy13

This happens at the point where my plugin tries to load the specified FQCN with "Class.forName()".  The class name was generated by calling "Mock(<classname>)" in my spec and writing "<mock>.getClass().getName()" into my test build file.

Any ideas what I can do here?  Will this be too much of a struggle, and should I just refactor the plugin so I can directly inject the mock instance?

--
You received this message because you are subscribed to the Google Groups "Spock Framework - User" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at http://groups.google.com/group/spockframework.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Mocking a class loaded from its FQCN

rfletcher
I'd separate out the loading of the class from the test subject so you can inject a different strategy in the test. In other words, instead of explicitly doing Class.forName use a function type with two implementations, one that does Class.forName and one that just returns a pre-determined instance. In your test you can use the latter version and have it return a mock.

On Thursday, March 26, 2015 at 2:38:11 PM UTC-7, David Karr wrote:
I'm trying to write an integration test for a Gradle plugin, using nebula-test.

The plugin provides the ability to specify a fully-qualified class name in an extension block, which the plugin's task then loads (using "Class.forName()") and instantiates to do work.  I could refactor the plugin so that I could inject a mock instance of that class into the code under test, but I'd like to see if it's possible to mock a class and then provide that class name to the plugin and let it load that class (which would already be loaded).

When I run the test, however, my plugin code fails with an error like this:

        java.lang.ClassNotFoundException: com.sun.proxy.$Proxy13

This happens at the point where my plugin tries to load the specified FQCN with "Class.forName()".  The class name was generated by calling "Mock(<classname>)" in my spec and writing "<mock>.getClass().getName()" into my test build file.

Any ideas what I can do here?  Will this be too much of a struggle, and should I just refactor the plugin so I can directly inject the mock instance?

--
You received this message because you are subscribed to the Google Groups "Spock Framework - User" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at http://groups.google.com/group/spockframework.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Mocking a class loaded from its FQCN

Justin Ryan
In reply to this post by KARR, DAVID
Just to be clear, it's not nebula-test that has a Class.forName, it's your plugin that has it, right?

On Thu, Mar 26, 2015 at 2:37 PM, KARR, DAVID <[hidden email]> wrote:
I'm trying to write an integration test for a Gradle plugin, using nebula-test.

The plugin provides the ability to specify a fully-qualified class name in an extension block, which the plugin's task then loads (using "Class.forName()") and instantiates to do work.  I could refactor the plugin so that I could inject a mock instance of that class into the code under test, but I'd like to see if it's possible to mock a class and then provide that class name to the plugin and let it load that class (which would already be loaded).

When I run the test, however, my plugin code fails with an error like this:

        java.lang.ClassNotFoundException: com.sun.proxy.$Proxy13

This happens at the point where my plugin tries to load the specified FQCN with "Class.forName()".  The class name was generated by calling "Mock(<classname>)" in my spec and writing "<mock>.getClass().getName()" into my test build file.

Any ideas what I can do here?  Will this be too much of a struggle, and should I just refactor the plugin so I can directly inject the mock instance?

--
You received this message because you are subscribed to the Google Groups "Spock Framework - User" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at http://groups.google.com/group/spockframework.
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Spock Framework - User" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at http://groups.google.com/group/spockframework.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

RE: Mocking a class loaded from its FQCN

KARR, DAVID
In reply to this post by rfletcher

Yeah, I already concluded I should go for that strategy.  I already refactored my plugin class to take this injection, but then I realized that I couldn’t see how to access the plugin (or task) instance from nebula-test.

 

From: [hidden email] [mailto:[hidden email]] On Behalf Of [hidden email]
Sent: Thursday, March 26, 2015 2:45 PM
To: [hidden email]
Subject: Re: Mocking a class loaded from its FQCN

 

I'd separate out the loading of the class from the test subject so you can inject a different strategy in the test. In other words, instead of explicitly doing Class.forName use a function type with two implementations, one that does Class.forName and one that just returns a pre-determined instance. In your test you can use the latter version and have it return a mock.

On Thursday, March 26, 2015 at 2:38:11 PM UTC-7, David Karr wrote:

I'm trying to write an integration test for a Gradle plugin, using nebula-test.

The plugin provides the ability to specify a fully-qualified class name in an extension block, which the plugin's task then loads (using "Class.forName()") and instantiates to do work.  I could refactor the plugin so that I could inject a mock instance of that class into the code under test, but I'd like to see if it's possible to mock a class and then provide that class name to the plugin and let it load that class (which would already be loaded).

When I run the test, however, my plugin code fails with an error like this:

        java.lang.ClassNotFoundException: com.sun.proxy.$Proxy13

This happens at the point where my plugin tries to load the specified FQCN with "Class.forName()".  The class name was generated by calling "Mock(<classname>)" in my spec and writing "<mock>.getClass().getName()" into my test build file.

Any ideas what I can do here?  Will this be too much of a struggle, and should I just refactor the plugin so I can directly inject the mock instance?

--
You received this message because you are subscribed to the Google Groups "Spock Framework - User" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at http://groups.google.com/group/spockframework.
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Spock Framework - User" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at http://groups.google.com/group/spockframework.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

RE: Mocking a class loaded from its FQCN

KARR, DAVID
In reply to this post by Justin Ryan

Correct.  That’s also a piece of code that I’ll have to evolve at some point, to control where I can load that class from, perhaps using JCL (https://github.com/kamranzafar/JCL/).

 

From: [hidden email] [mailto:[hidden email]] On Behalf Of Justin Ryan
Sent: Thursday, March 26, 2015 2:50 PM
To: [hidden email]
Subject: Re: Mocking a class loaded from its FQCN

 

Just to be clear, it's not nebula-test that has a Class.forName, it's your plugin that has it, right?

 

On Thu, Mar 26, 2015 at 2:37 PM, KARR, DAVID <[hidden email]> wrote:

I'm trying to write an integration test for a Gradle plugin, using nebula-test.

The plugin provides the ability to specify a fully-qualified class name in an extension block, which the plugin's task then loads (using "Class.forName()") and instantiates to do work.  I could refactor the plugin so that I could inject a mock instance of that class into the code under test, but I'd like to see if it's possible to mock a class and then provide that class name to the plugin and let it load that class (which would already be loaded).

When I run the test, however, my plugin code fails with an error like this:

        java.lang.ClassNotFoundException: com.sun.proxy.$Proxy13

This happens at the point where my plugin tries to load the specified FQCN with "Class.forName()".  The class name was generated by calling "Mock(<classname>)" in my spec and writing "<mock>.getClass().getName()" into my test build file.

Any ideas what I can do here?  Will this be too much of a struggle, and should I just refactor the plugin so I can directly inject the mock instance?

--
You received this message because you are subscribed to the Google Groups "Spock Framework - User" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at http://groups.google.com/group/spockframework.
For more options, visit https://groups.google.com/d/optout.

 

--
You received this message because you are subscribed to the Google Groups "Spock Framework - User" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at http://groups.google.com/group/spockframework.
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Spock Framework - User" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at http://groups.google.com/group/spockframework.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

RE: Mocking a class loaded from its FQCN

KARR, DAVID
In reply to this post by rfletcher

According to one of the nebula-test devs (I filed an issue), you can’t inject spock mocks using IntegrationSpec.  It runs a separate process for that.

 

From: [hidden email] [mailto:[hidden email]] On Behalf Of [hidden email]
Sent: Thursday, March 26, 2015 2:45 PM
To: [hidden email]
Subject: Re: Mocking a class loaded from its FQCN

 

I'd separate out the loading of the class from the test subject so you can inject a different strategy in the test. In other words, instead of explicitly doing Class.forName use a function type with two implementations, one that does Class.forName and one that just returns a pre-determined instance. In your test you can use the latter version and have it return a mock.

On Thursday, March 26, 2015 at 2:38:11 PM UTC-7, David Karr wrote:

I'm trying to write an integration test for a Gradle plugin, using nebula-test.

The plugin provides the ability to specify a fully-qualified class name in an extension block, which the plugin's task then loads (using "Class.forName()") and instantiates to do work.  I could refactor the plugin so that I could inject a mock instance of that class into the code under test, but I'd like to see if it's possible to mock a class and then provide that class name to the plugin and let it load that class (which would already be loaded).

When I run the test, however, my plugin code fails with an error like this:

        java.lang.ClassNotFoundException: com.sun.proxy.$Proxy13

This happens at the point where my plugin tries to load the specified FQCN with "Class.forName()".  The class name was generated by calling "Mock(<classname>)" in my spec and writing "<mock>.getClass().getName()" into my test build file.

Any ideas what I can do here?  Will this be too much of a struggle, and should I just refactor the plugin so I can directly inject the mock instance?

--
You received this message because you are subscribed to the Google Groups "Spock Framework - User" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at http://groups.google.com/group/spockframework.
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Spock Framework - User" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at http://groups.google.com/group/spockframework.
For more options, visit https://groups.google.com/d/optout.