JSF-Testing with embedded TomEE: Manipulate injected object

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
6 messages Options
hfe
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

JSF-Testing with embedded TomEE: Manipulate injected object

hfe
Hello,
I have a JSF-Project with one class called Label and one xhtml-page, called label.xhtml. In label.xhtml the method Label.getValue() is called via injection. The test LabelTest runs a embedded container and in the a test method label.xhtml is requested and the body content will be checked. So far everything is fine, but I would like to change the value of the attribute Label.value in my test so the test can assert his own set value and not the value of the Postconstruct-method of class Label.

I put a breakpoint in the constructor of class Label. So I can see the stacktrace and I read the code of many of these methods. Maybe it is possible to change the produces class, so I can put there my own AbstractProducer in some way?

Code on GitHub





Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: JSF-Testing with embedded TomEE: Manipulate injected object

Romain Manni-Bucau
Hi

You can @specializes the bean or just use a filter to do it

Le 22 avr. 2017 13:34, "hfe" <[hidden email]> a écrit :

> Hello,
> I have a JSF-Project with one class called Label and one xhtml-page, called
> label.xhtml. In label.xhtml the method Label.getValue() is called via
> injection. The test LabelTest runs a embedded container and in the a test
> method label.xhtml is requested and the body content will be checked. So
> far
> everything is fine, but I would like to change the value of the attribute
> Label.value in my test so the test can assert his own set value and not the
> value of the Postconstruct-method of class Label.
>
> I put a breakpoint in the constructor of class Label. So I can see the
> stacktrace and I read the code of many of these methods. Maybe it is
> possible to change the produces class, so I can put there my own
> AbstractProducer in some way?
>
> Code on GitHub <https://github.com/feidner/stackoverflow-label>
>
> <http://tomee-openejb.979440.n4.nabble.com/file/n4681575/stacktrace.png>
>
>
>
>
>
>
>
> --
> View this message in context: http://tomee-openejb.979440.
> n4.nabble.com/JSF-Testing-with-embedded-TomEE-Manipulate-injected-object-
> tp4681575.html
> Sent from the TomEE Users mailing list archive at Nabble.com.
>
hfe
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: JSF-Testing with embedded TomEE: Manipulate injected object

hfe
Very good, I didn't know @Specializes, this works good.
But maybe you can give me a hint how I can do it with a filter? I was looking at the code of Arquillian-Warp, I think there a filter is used so that Warp is working? But I didn't get it, maybe I have to invest more time in reading the Warp-Code.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: JSF-Testing with embedded TomEE: Manipulate injected object

Romain Manni-Bucau
The filter solution requires to catch the request needing the change (based
on the uri or a global flag), lookup the bean and set the value there.

Warp is a bit different and not sure it works well with embedded container.
Goal is to proxy all requests to be able to execute remote code to validate
code was executed. It is an awesome solution but you will probably need to
migrate to remote container.


Romain Manni-Bucau
@rmannibucau <https://twitter.com/rmannibucau> |  Blog
<https://blog-rmannibucau.rhcloud.com> | Old Blog
<http://rmannibucau.wordpress.com> | Github <https://github.com/rmannibucau> |
LinkedIn <https://www.linkedin.com/in/rmannibucau> | JavaEE Factory
<https://javaeefactory-rmannibucau.rhcloud.com>

2017-04-25 9:10 GMT+02:00 hfe <[hidden email]>:

> Very good, I didn't know @Specializes, this works good.
> But maybe you can give me a hint how I can do it with a filter? I was
> looking at the code of Arquillian-Warp, I think there a filter is used so
> that Warp is working? But I didn't get it, maybe I have to invest more time
> in reading the Warp-Code.
>
>
>
> --
> View this message in context: http://tomee-openejb.979440.
> n4.nabble.com/JSF-Testing-with-embedded-TomEE-Manipulate-injected-object-
> tp4681575p4681589.html
> Sent from the TomEE Users mailing list archive at Nabble.com.
>
hfe
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: JSF-Testing with embedded TomEE: Manipulate injected object

hfe

Thank you, I got it also with der ServletFilter, very easy in the end.
hfe
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: JSF-Testing with embedded TomEE: Manipulate injected object

hfe
Hi,

in my previous solutions I was able to use Mocks just with wrapper classes. So, I was reading more and more code of TomEE and I found out that I can use an Observer for directly mocking the injected object.


In a Test I call:

BeanToMock bean = Mockito.mock(BeanToMock.class);
when(bean.callme()).thenReturn("Jedi");
HfeObserver.addProducer(BeanToMock.class, () -> bean);

// start container
// request website with #{beanToMock.callme()} included


And the file /META-INF/org.apache.openejb.extension contains the name of this Observer:

----------

public class HfeObserver {

    public static final Map<Class<?>, HfeSupplier> PRODUCERS = new HashMap<>();

    public static void addProducer(Class<?> clazz, Supplier supplier) {
        PRODUCERS.get(clazz).setSupplier(supplier);
    }

    public void observer(@Observes WebBeansContextBeforeDeploy event) {
        event.getContext().getBeanManagerImpl().getNotificationManager().addObserver(new HfeObserverMethod(), ProcessInjectionTarget.class);
    }

    private static class HfeObserverMethod implements ObserverMethod, GenericBeanEvent, Extension {

        @Override
        public Class<?> getBeanClass() {
            return HfeObserverMethod.class;
        }

        @Override
        public Type getObservedType() {
            return null;
        }

        @Override
        public Set<Annotation> getObservedQualifiers() {
            return Sets.newHashSet(AnyLiteral.INSTANCE);
        }

        @Override
        public Reception getReception() {
            return null;
        }

        @Override
        public TransactionPhase getTransactionPhase() {
            return null;
        }

        @Override
        public void notify(Object event) {
            if (event instanceof GProcessInjectionTarget) {
                GProcessInjectionTarget injectionTarget = (GProcessInjectionTarget) event;
                Class<?> clazz = injectionTarget.getAnnotatedType().getJavaClass();
                HfeSupplier supplier = PRODUCERS.get(clazz);
                if (supplier == null) {
                    PRODUCERS.put(clazz, supplier = new HfeSupplier());
                }
                InjectionTarget target = injectionTarget.getInjectionTarget();
                assert target != null;
                injectionTarget.setInjectionTarget(new HfeInjectionTarget(target, supplier));
            }
        }

        @Override
        public Class<?> getBeanClassFor(Class<?> eventClass) {
            return null;
        }
    }


    private static class HfeInjectionTarget implements InjectionTarget {

        private InjectionTarget target;
        private Supplier supplier;

        public HfeInjectionTarget(InjectionTarget target, Supplier supplier) {
            assert supplier != null;
            this.target = target;
            this.supplier = supplier;
        }

        public void inject(Object instance, CreationalContext ctx) {
            target.inject(instance, ctx);
        }

        public void postConstruct(Object instance) {
            target.postConstruct(instance);
        }

        public void preDestroy(Object instance) {
            target.preDestroy(instance);
        }

        public Object produce(CreationalContext creationalContext) {
            return supplier.get() == null ? target.produce(creationalContext) : supplier.get();
        }

        public void dispose(Object instance) {
            target.dispose(instance);
        }

        public Set<InjectionPoint> getInjectionPoints() {
            return target.getInjectionPoints();
        }

    }

    public static class HfeSupplier implements Supplier {
        private Supplier supplier;


        public void setSupplier(Supplier supplier) {
            this.supplier = supplier;
        }

        @Override
        public Object get() {
            return supplier == null ? null : supplier.get();
        }
    }

}
Loading...