Mock field injection

Hello,

in my bpmn process, I like to mock a send task. The send task uses a java-delegate to send a mail. To distinguish several send tasks, I inject a constant value into the task (Field injection).

To test the process within a unit test, i do the following steps:

//registers mocks for all delegateExpressions
autoMock(“process”);

//registers a FluentJavaDelegateMock for the send task
DelegateExpressions.registerJavaDelegateMock(“delegateName”);

Job processJob = getProcessJob();
execute(processJob);

Then, I receive the following error:

org.camunda.bpm.engine.exception.NullValueException: Field definition uses unexisting field ‘mailName’ on class org.camunda.bpm.extension.mockito.mock.FluentJavaDelegateMock: field is null

This shows that the field injection was not mocked correctly.
Could somebody please help me to address this issue?

Thank you!

Hi

I am the author of the camunda-bpm-mockito extension. I never use field injection, so I guess you discovered a “missing feature”.
But: I am also not sure, if the regular camunda “mocks.register” will work here, since filed injection works via reflection and thus cannot be mocked.
Your best chance would be to register not a mock but a fake instance, so in your test, provide a MailDelegate class that has all required fields but does nothing inside the execute() method. Create a spy for it and register it via “registerInstance” instead of “registerJavaDelegateMock”. You should then be able to verify the mailDelegate was called correctly.

Jan

Hi @jangalinski, I have a similar problem where I get NullValueException because of FixedValue object which is part of my delegate class. I have mocked the delegate class using Mocks.register(), but not sure how can I mock the FixedValue field of the delegate class. Can you please help me? Thank you

Quite sure this won’t work with mockito mocks … in those cases, you could write a “fake” instance … a class that implements an empty execute() method (or stores executions in a list, …) but has the same name and injection behaviour as the original delegate.

1 Like

Hello @jangalinski

For single mock (not autoMock(“process”)) could be possible to work with filed injection if specifies extra interfaces the mock should supply:

public FluentJavaDelegateMock(Class<?>... injectionInterfaces) {
            super(mock(JavaDelegate.class, withSettings().extraInterfaces(injectionInterfaces)), DelegateExecution.class);
} 

 // injection interface for field "foo"
  interface InjectionInterface {
     public void setFoo(Expression exprFoo)
  }

Unfortunatelly FluentJavaDelegateMock is final and FluentMock is package restricted.

Roman

I m not sure that I get the use case. So your JavaDelegate is not only a JavaDelegate, but also - let’s say - a CustomerService? And you need to mock both delegate behavior and service behavior?

Well the FluentMock stuff wouldn’t care for that … you know that the registerXXXMock(MyDelegate.class) methods are just convenient shortcuts? It all falls back to the “registerInstance()”, so you can easily create any instance (mock or “real”) and register it under the name specified in the bpmn model. Maybe that already helps? In more complex Test-Scenarios, I tend to write “fake” instances of my Delegates, that are not mocks, but rather implement the execute() method to increase a counter, store a DTO in a collection, …

What we can easily do (do not remember why I ever chose not to) is open the Fluent classes in the extension, so you can extend locally …

edit: opened an issue https://github.com/camunda/camunda-bpm-mockito/issues/122

Hello @jangalinski
Thank you for your response. The case is: I have a number of JavaDelegates with the same set of injecting fields for which I create an interface.

But You are right, this is more for first prototyping.
It would be nice to make FluentMock and supported classes more open to extent. Sometimes it is easy to start not from scratch.

best regards
Roman