Note that there are some explanatory texts on larger screens.

plurals
  1. POCDI Extensions: Can I expose one interface in two scopes?
    text
    copied!<p>I have an interface in a unit testing framework: CDIMocker. I'm currently using an interceptor to allow mocking in a CDI container. It's an experiment - one of a couple of approaches to unit testing I'm considering. (The other main contender is to use constructor and method injection for all beans and unit test outside CDI - in which case this work becomes more a learning exercise in CDI Extensions).</p> <p>I have two custom scopes - TestClassScoped and TestMethodScoped. My JUnit4 custom runner wraps the appropriate Class and Method blocks in statements that start and stop these scopes as needed. It also starts an instance of Weld-SE if needed. It knows if it's in CDI because the Extension remembers.</p> <p>The mocker interface is the same wherever it us used. It would be nice to expose it in both scopes, so I could</p> <pre><code> // Sadly Static Injection currently doesn't work, but if it did @Inject @TestClassScoped private static CdiMocker s_classScopedMocker @Inject @TestMethodScoped private CdiMocker m_methodScopedMocker </code></pre> <p>There are other obvious ways. I currently have a factory method on a singleton outside CDI that can return either of these instances (ThreadLocal), or create a new short lived one. I have also had success creating two concrete classes and declaring different scopes on them. </p> <p>I've tried using Producer Methods annotated as above, but no luck. Perhaps a simple mistake, perhaps a misunderstanding. </p> <pre><code>@Produces @TestClassScoped public CdiMocker getClassScopedMockerForCdi() { return getTestClassContext().getMocker(); } @Produces @TestMethodScoped public CdiMocker getMethodScopedMockerForCdi() { return getTestMethodContext().getMocker(); } </code></pre> <p>I thought from some part of the CDI documentation it was possible to declare scopes on injection points as I have done, but I note that the Instance&lt;> interface does not allow me to select() using scoped annotation so maybe that is wrong.</p> <p>I could provide two qualifiers. Can an annotation be a Qualifier and a Scope at the same time?</p> <p>Another idea would be to have my extension provide two Bean&lt;CdiMocker&gt;, both exposing the same class but in different scopes. They could also provide custom create() and destroy() because the CdiMocker instances are managed by my two custom Contexts. The impression I get of CDI is that a given Class can only live in one Scope, so would this be Wrong?</p> <p>Any suggestions on what is best?</p> <p>Thanks - Richard</p> <p>(I'd love to open source the result, but have done enough in work time I'd have to ask so not likely. The business argument would be public review. I use an Interceptor now with the disadvantage that it has to be left in place, but wonder if I could achieve something by intercepting the bean lifecycle in the extension. We can use Alternatives for things like the comms layer that talks to our legacy app server, but for some things a single unit test wants a custom mock and Alternatives are too global.)</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload