How to Test individual JavaDelegate Tasks?

1,693 views
Skip to first unread message

Alfonso Mateos Alarcón

unread,
Aug 26, 2014, 6:25:20 AM8/26/14
to camunda-...@googlegroups.com
Hi guys,

I already tested unit tests for my processes, checking out the flows, and the variables, and mocking the service tasks.
But how could I test some individual service tasks?

What I'd like to get is to test those service tasks but at the same time, mocking the EJB's or the beans that I'm calling from my java delegate.
I was thinking on mockito, but I don't know where to start with... I'd like not to go to Arquillian if that's avoidable, so that I could just test the classes I want.

Thanks in advance!

Bernd Rücker (camunda)

unread,
Aug 27, 2014, 5:32:31 AM8/27/14
to camunda-...@googlegroups.com

Hi Alfonso.

 

I think it makes very much sense if you try to mock out the real service EJB‘s – as you keep the tests much easier and need less infrastructure. See my proposed new image for testing scopes in https://app.camunda.com/jira/browse/CAM-2116 - we already work with this one for quite a while in consulting and have good experience with it. So in that image you try to keep in scope 1.

 

Then Mockito is a good way to go to mock out the EJB’s or real services you need. You just need a mechanism to inject the mocks in your JavaDelegates. That depend a bit on your infrastructure (DI-Container? Spring, CDI, …?) – but is most of the time doable without Arquillian or the like.

 

Cheers

Bernd

--
You received this message because you are subscribed to the Google Groups "camunda BPM users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to camunda-bpm-us...@googlegroups.com.
To post to this group, send email to camunda-...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/camunda-bpm-users/9305f1c9-0a8c-428b-b463-b355c000d484%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Alfonso Mateos Alarcón

unread,
Aug 27, 2014, 6:16:35 AM8/27/14
to camunda-...@googlegroups.com
Hi Bernd, I think the key is in the sentence:


You just need a mechanism to inject the mocks in your JavaDelegate

Could you please show me any example or piece of code that shows how to do so with a small infrastucture? (i.e. with mockito, or just the way you use the most).
The EJB's we are calling from our JavaDelegates are injected via CDI, I don't see how to swap them for some mocks and still have my real JavaDelegate code tested...

Thanks in advance.

Bernd Rücker (camunda)

unread,
Aug 27, 2014, 6:21:26 AM8/27/14
to camunda-...@googlegroups.com

Do you use CDI named beans as delegateExpressions?

 

Or how to you hook in the delegates in the BPMN.xml?

Alfonso Mateos Alarcón

unread,
Aug 27, 2014, 6:47:45 AM8/27/14
to camunda-...@googlegroups.com
I use CDI named beans as delegateExpressions.

Bernd Rücker (camunda)

unread,
Aug 27, 2014, 8:15:26 AM8/27/14
to camunda-...@googlegroups.com

Hi Alfonso.

 

Then you already have the problem of how to run a JUnit Test without CDI – correct? How did you solve this?

 

I think there are three basic ways of doing this (if we do not use Arquillian):

-          Start a CDI container for your tests (e.g. JBoss Weld)

-          Start some testing lightweight CDI container (e.g. http://needle.spree.de/)

-          Using the camunda mocking facility

 

For the third way you can call “Mocks.register(“myCdiBean”, someObject)”. In this case you can hand in the delegates from the test case and do the injection of Mocks yourself there. Make sure you add the MockExpressionManager to your ProcessEngineCOnfiguration (typed from my head – name might be a bit different).

 

The last one has the advantage that you do not need any environment. And you can do mocking really easy. But if you have too much delegates it might get a bit unhandy – so using a CDI container might be an option.

Alfonso Mateos Alarcón

unread,
Aug 28, 2014, 3:13:16 AM8/28/14
to camunda-...@googlegroups.com
Hi Bernd,

I don't have the problem of running a JUnit without CDI, let me explain why, and where do I have the problem now...

I've got a JavaDelegate, referenced from my serviceTask as a delegate expression. Let's suppose that class is something like this:

@Named("myServiceTaskBean")
public class myBean {

}

If I use mock register with it and I use the configuration you mentioned, it works without a CDI container like a charm (is the option 3 you mentioned). 


The problem comes now if I have this:

@Named("myServiceTaskBean")
public class MyBean implements JavaDelegate {

     @Inject
      MyBusinessLogicEjb myBusinessLogicEjb;

        public void execute(DelegateExecution execution) throws Exception {
              some logic here...
              myBusinessLogicEjb.doSomething();
              some more logic here too...
      }

}

My intention would be: 
- Test the real MyBean class instance, with all of its logic inside, but mocking the internal MyBusinessLogicEjb class, and replacing that call for a fake one.
- I can do this with Arquillian (seizing the @Named and the @SupressWarnings("cdi-ambiguous-name")) and it works: I can test the real JavaDelegate but with a fake MyBusinessLogicEjb.
- Do you know if I can get the equivalent test but just going thru the option 3 you mentioned?

Thanks a lot for your attention, Bernd.

Bernd Rücker (camunda)

unread,
Aug 28, 2014, 3:19:04 AM8/28/14
to camunda-...@googlegroups.com

OK great!

 

Just add a „setMyBusinessLogicEjb“ method and fill that from your test case before setting the Mock. Or use a reflection helper in the test case if you don’t want to have the setters…

 

Von: camunda-...@googlegroups.com [mailto:camunda-...@googlegroups.com] Im Auftrag von Alfonso Mateos Alarcón
Gesendet: Donnerstag, 28. August 2014 09:13
An: camunda-...@googlegroups.com
Betreff: Re: [camunda-bpm-users] How to Test individual JavaDelegate Tasks?

 

Hi Bernd,

--

You received this message because you are subscribed to the Google Groups "camunda BPM users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to camunda-bpm-us...@googlegroups.com.
To post to this group, send email to camunda-...@googlegroups.com.

Alfonso Mateos Alarcón

unread,
Aug 28, 2014, 4:55:04 AM8/28/14
to camunda-...@googlegroups.com

Hi Bernd do Camunda Mocks have something like @InjectMocks of Mockito, or should I manually assign every single mock to every single inner field of my JavaDelegate? That annotation does the "magic" and assign thru reflection the inner beans that have been told to be a Mock, as told at: http://stackoverflow.com/questions/16467685/difference-between-mock-and-injectmocks

@Mock creates a mock. @InjectMocks creates an instance of the class and injects the mocks that are created with the @Mock (or @Spy) annotations into this instance. Note that you must use @RunWith(MockitoJUnitRunner.class) or Mockito.initMocks(this) to initialise these mocks and inject them.

@RunWith(MockitoJUnitRunner.class)
public class SomeManagerTest {

    @InjectMocks
    private SomeManager someManager;

    @Mock
    private SomeDependency someDependency; // this will be injected into someManager

     //tests...

}

Thanks in advance for your valuable help!

Alfonso Mateos Alarcón

unread,
Aug 28, 2014, 6:29:20 AM8/28/14
to camunda-...@googlegroups.com
Bernd, I finally got it working as you suggested, via reflection:

// Register mock for internal bean

MyBusinessLogicEjb myBusinessLogicEjb = new ExternalBeanMock();

Mocks.register("myBusinessLogicEjb", myBusinessLogicEjb);

StorePDFDelegate mock = new StorePDFDelegate();

Mocks.register("archiveService", mock);

final Field field = mock.getClass().getDeclaredField("myBusinessLogicEjb");

field.setAccessible(true);

field.set(mock, myBusinessLogicEjb);


I still have one question: I'm registering the real JavaDelegate class as a Mock, because I don't figure out how to get the in-memory test to instantiate my cdi delegate expression... do you figure out how to avoid mocking it? I still would mock the inner "myBusinessLogicEjb" bean...


Thanks in advance!


Bernd Rücker (camunda)

unread,
Aug 28, 2014, 8:38:29 AM8/28/14
to camunda-...@googlegroups.com

Hi Alfonso.

 

Looks good! You could now use Mockito to mock the MyBusinessLogicEjb

 

I'm registering the real JavaDelegate class as a Mock

 

But that’s exactly what you want to do – no? Maybe the name “Mock” is not completely correct here – but you create the JavaDelegate instance yourself (instead of the CDI container) and hand it over to the process engine to use it with the given name. Exactly what you want.

 

Von: camunda-...@googlegroups.com [mailto:camunda-...@googlegroups.com] Im Auftrag von Alfonso Mateos Alarcón
Gesendet: Donnerstag, 28. August 2014 12:29
An: camunda-...@googlegroups.com
Betreff: Re: [camunda-bpm-users] How to Test individual JavaDelegate Tasks?

 

Bernd, I finally got it working as you suggested, via reflection:

--

You received this message because you are subscribed to the Google Groups "camunda BPM users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to camunda-bpm-us...@googlegroups.com.
To post to this group, send email to camunda-...@googlegroups.com.

Alfonso Mateos Alarcón

unread,
Aug 29, 2014, 3:58:20 AM8/29/14
to camunda-...@googlegroups.com
Thanks a lot for your help, Bernd, and for your feeback confirming my current approach :-)

Jan Galinski

unread,
Aug 29, 2014, 11:49:11 AM8/29/14
to camunda-...@googlegroups.com
Hi Alfonso

This is in fact the very usecase we build the camunda-bpm-needle extension for. Check out https://github.com/camunda/camunda-bpm-needle. It's already very stable and we have been using it in a client project for a year now.
Basically, it combines the processRule for setting up the engine and the needle4j (formerly needle) rule for mocking dependencies. Needles trick is, that it injects a mock whereever you did not specify anything else. Have a look at the examples and feel free to come back to me if you need more information.

Hopefully, we will get a1.0 release at the comminty day in september, there is just some documentation missing.

Regards
Jan

gcal...@gmail.com

unread,
Sep 1, 2014, 2:56:05 AM9/1/14
to camunda-...@googlegroups.com
Thanks Jan!

I had a look to Needle4j and it looks good. It seems to use @Mock and @ObjectUnderTest annotations. But I wanted to ask you how would you face this situation I will expose to you, to know if I understand it right.

Let's suppose we have a process wich calls a serviceTask JavaDelegate, and then this JavaDelegate has some CDI injects from some other beans which execute some business logic:

@Named("serviceTask)
public class MyServiceTask implements JavaDelegate {

@Inject BusinessLogicBean businessLogicBean;

public void execute (Execution execution) {
...
businessLogicBean.someMethod(...)
...

I'd like to test the real code inside MyServiceTask, but mock the code inside BusinessLogicBean. How would the test look like? Something like this?


@Mock BusinessLogicBean businessLogicBean;
@ObjectUnderTest MyServiceTask serviceTask;


@Test
@Deployment(resources = "test-process.bpmn")
public void should_deploy_and_start_process_via_starter_bean() {
Mocks.register("serviceTask", serviceTask);

...
}

Jan Galinski

unread,
Sep 1, 2014, 4:23:14 AM9/1/14
to camunda-...@googlegroups.com, gcal...@gmail.com
Yes, this is how you could do it (and would if you had to mock complex behavior).
You should check if you really need the "objectUnderTest", though. Since you are working with a JavaDelegate, the only thing it can do (related to the process flow you are testing) is modifying process variables or raising BPMNErrors.  You could mock this easily directly on the JavaDelegate level without bothering about the LogicBean. 

Then of course you should write other tests (using needle4j preferably) that  test the BusinessLogicBean and the Delegate implementation.

BTW: for mocking of JavaDelegates and Listeners, I recently added an extension project: https://github.com/camunda/camunda-bpm-mockito/ ... that hopefully also becomes 1.0 this month. 

Bernd Rücker (camunda)

unread,
Sep 1, 2014, 5:36:32 AM9/1/14
to camunda-...@googlegroups.com, gcal...@gmail.com

Hi Jan.

 

I am in favor of using the real JavaDelegate as I consider it part of the process model (logically) and mock the service only. This way you can test the whole process model with data mapping in one go without external service dependencies. And I don’t see a major downside of it.

 

Cheers

Bernd

 

Von: camunda-...@googlegroups.com [mailto:camunda-...@googlegroups.com] Im Auftrag von Jan Galinski
Gesendet: Montag, 1. September 2014 10:23
An: camunda-...@googlegroups.com
Cc: gcal...@gmail.com
Betreff: Re: [camunda-bpm-users] How to Test individual JavaDelegate Tasks?

 

Yes, this is how you could do it (and would if you had to mock complex behavior).

--

You received this message because you are subscribed to the Google Groups "camunda BPM users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to camunda-bpm-us...@googlegroups.com.
To post to this group, send email to camunda-...@googlegroups.com.

Reply all
Reply to author
Forward
0 new messages