You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomee.apache.org by hfe <a...@h41.de> on 2017/04/21 19:33:27 UTC

JSF-Testing with embedded TomEE: Manipulate injected object

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.

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

Posted by hfe <a...@h41.de>.
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&lt;?>, 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();
        }
    }

}



--
View this message in context: http://tomee-openejb.979440.n4.nabble.com/JSF-Testing-with-embedded-TomEE-Manipulate-injected-object-tp4681575p4681697.html
Sent from the TomEE Users mailing list archive at Nabble.com.

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

Posted by hfe <a...@h41.de>.
Thank you, I got it also with der ServletFilter, very easy in the end.



--
View this message in context: http://tomee-openejb.979440.n4.nabble.com/JSF-Testing-with-embedded-TomEE-Manipulate-injected-object-tp4681575p4681625.html
Sent from the TomEE Users mailing list archive at Nabble.com.

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

Posted by Romain Manni-Bucau <rm...@gmail.com>.
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 <a...@h41.de>:

> 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.
>

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

Posted by hfe <a...@h41.de>.
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.

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

Posted by Romain Manni-Bucau <rm...@gmail.com>.
Hi

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

Le 22 avr. 2017 13:34, "hfe" <a...@h41.de> 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.
>