Inverting dependencies for extensions

My language plugin has some dependencies very tightly coupled and I'm trying to find the right approach to inverting them, particularly for unit testing.  I discovered that the factoryClass and factoryArgument attributes can be used in plugin.xml.  This seems like it gets me pretty close, except I'm not sure how to swap out extensions during unit tests.  Any ideas?

To give some context, instead of registering an external annotator like this -

 
<externalAnnotator language="Haskell" implementationClass="com.haskforce.highlighting.annotation.external.HaskellExternalAnnotator"/>


I could register it like this -

 
<externalAnnotator language="Haskell"
                   factoryClass="com.haskforce.highlighting.annotation.external.HaskellExternalAnnotatorFactory"
                   factoryArgument="com.haskforce.highlighting.annotation.external.GhcMod"/>


Here's a simple implementation of the factory -

 
public class HaskellExternalAnnotatorFactory implements ExtensionFactory {
    @Override
    public
Object createInstance(String factoryArgument, String implementationClass) {
        try {
            return new HaskellExternalAnnotator((Class<? extends GhcMod>)Class.forName(factoryArgument));
        
} catch (ClassNotFoundException e) {
            e.printStackTrace();
            throw new
RuntimeException(e);
        
}
    }
}


While this works for production, it still leaves me wondering how to use a different factoryArgument during tests.  For instance, I am using the LightPlatformCodeInsightFixtureTestCase.

Maybe this is the completely wrong approach.  If so, is there a better way to invert these kind of dependencies?

Feel free to look at the current source if you need more context - https://github.com/carymrobbins/intellij-haskforce

4 comments
Comment actions Permalink

The plugin.xml registration mechanism does not currently have any support for using different registration parameters in production and test mode. What you can do instead is check ApplicationManager.getApplication().isUnitTestMode() in your ExtensionFactory implementation and use different classes depending on whether you're in unit test mode or not.

0
Comment actions Permalink

That sounds like a good idea, didn't realize that the Application had that method.  Thanks!

0
Comment actions Permalink

While I am trying out the factoryClass approach, is there a better way to do this in IntelliJ?  I'm assuming this isn't the first time this kind of thing has been discussed.  How are other features/tools tested without fully integrating with external processes?

0
Comment actions Permalink

Actually IntelliJ's own tests mostly use the actual production implementations of everything. We find that the benefits of testing the actual system as it runs in production exceed the costs of slow test execution.

0

Please sign in to leave a comment.