0

I have a Spring boot application which receives messages from MQ and create a file and store all the data in that file.

I am trying to test this application but I encountered "MQRFH2 has an invalid value" error when I am using a mock bean for this class.

The code for the Main Application is :

@SpringBootApplication
@EnableJms
@EnableScheduling
public class FileMQApplication {
    void receiveMessage() {
        try {
            MQQueueManager queueManager = getMQQueueManager(queueManagerName);
            
            MQQueue queue = queueManager.accessQueue(queueName, MQConstants.MQOO_INPUT_SHARED);
            
            while (true) {
                try {
                    MQGetMessageOptions gmo = getMQMessageOptions();
                    gmo.options = setMessageOptions();
                    System.out.println("beforeee receive msg creationnn ....");
                    MQMessage receiveMsg = getNewMessage();
                    System.out.println("beforeee q getttttttt ....");
                    queue.get(receiveMsg, gmo);
                    System.out.println("afterr q getttttttt ....");
                    processMessage(receiveMsg);
                    System.out.println("afterr proesssss ....");
                } catch (MQException mqe) {// exception handling code}
            }
            queue.close(); queueManager.close(); queueManager.disconnect();
        } catch (Exception ex) {// exception handling code}
    }
    
    // methods created to help mocking in Unit Testing
    protected  MQMessage getNewMessage() {
        return new MQMessage();
    }
    
    protected MQGetMessageOptions getMQMessageOptions() {
        return new MQGetMessageOptions();
    }
    
    protected MQQueueManager getMQQueueManager(String QMName) throws MQException {
        return new MQQueueManager(QMName);
    }
    
    protected MQRFH2 getMQRFH2(MQMessage msg) throws MQDataException, IOException {
        return new MQRFH2(msg);
    }
    
    protected int setMessageOptions() {
        return CMQC.MQGMO_PROPERTIES_FORCE_MQRFH2 + CMQC.MQGMO_FAIL_IF_QUIESCING + CMQC.MQGMO_NO_WAIT;
    }

    private void processMessage(MQMessage message) {
        try {
            byte[] a = message.messageId;
            String messageId = toHex(a);
            
            message.seek(0);
            if (CMQC.MQFMT_RF_HEADER_2.equals(message.format)) {
                
                MQRFH2 rfh2 = getMQRFH2(message);   // error appears here
                
                int strucLen = rfh2.getStrucLength();
                int encoding = rfh2.getEncoding();
                int CCSID = rfh2.getCodedCharSetId();
                String format = rfh2.getFormat();
                int flags = rfh2.getFlags();
                int nameValueCCSID = rfh2.getNameValueCCSID();
                String[] folderStrings = rfh2.getFolderStrings();
                byte[] b = new byte[message.getDataLength()];
                message.readFully(b);
            }
        } catch (Exception e) { e.printStackTrace(); }
    }
}

The code for TestClass is :

I am mocking the MQ connectivity related classes like MQQueueManager, MQQueue, MQGetMessageOptions, MQMessage, MQRFH2. I have made the FileMQApplication bean as Spy because I want to mock the methods: getMQRFH2, getNewMessage, getMQMessageOptions, getMQQueueManager so that the rest code is tested with test data.

QQ. Is there some specific way to Mock RFH2 that I am not aware of or is there some mistake while creating Mock bean for MQRFH2 ?

@TestMethodOrder(OrderAnnotation.class)
@SpringBootTest
class FileMQApplicationTests {
    
    @Mock
    private MQQueueManager queueManager;
    
    @Mock
    private MQQueue queue;
    
    @Mock
    private MQGetMessageOptions gmo;
    
    @Mock
    private MQMessage msg;
    
    @Mock
    private MQRFH2 rfh2;
    
    @Spy
    FileMQApplication mainApp;
    
    // values are fetched from properties file under **src/test**
    @Value("${mq.queueName}")
    private String queueName;
    @Value("${mq.host}")
    private String host;
    @Value("${mq.port}")
    private int port;
    @Value("${mq.queueManager}")
    private String queueManagerName;
    @Value("${mq.channel}")
    private String channelName;
    @Value("${dir.location}")
    private String directoryLocation;
    @Value("${rejected.dir.location}")
    private String rejectedDirLocation;
    @Value("${mq.userId:}")
    private String uid;
    @Value("${mq.password:}")
    private String pwd;
    @Value("${mq.encryptionSalt:}")
    private String encryptionSalt;
    
    @BeforeEach
    void init() {
        // setting the property values in main app from test properties
        ReflectionTestUtils.setField(mainApp, "queueName", queueName);
        ReflectionTestUtils.setField(mainApp, "host", host);
        ReflectionTestUtils.setField(mainApp, "port", port);
        ReflectionTestUtils.setField(mainApp, "queueManagerName", queueManagerName);
        ReflectionTestUtils.setField(mainApp, "channelName", channelName);
        ReflectionTestUtils.setField(mainApp, "directoryLocation", directoryLocation);
        ReflectionTestUtils.setField(mainApp, "rejectedDirLocation", rejectedDirLocation);
        ReflectionTestUtils.setField(mainApp, "uid", uid);
        ReflectionTestUtils.setField(mainApp, "pwd", pwd);
        ReflectionTestUtils.setField(mainApp, "encryptionSalt", encryptionSalt);    
        try {
            when(queueManager.accessQueue(queueName, MQConstants.MQOO_INPUT_SHARED)).thenReturn(queue);
            doNothing().when(queue).get(msg, gmo);
            doNothing().when(msg).seek(0);
        } catch (MQException e) { e.printStackTrace(); } catch (EOFException e) { e.printStackTrace(); }
        
        return;
    }
    
    @Test
    @DisplayName("Test 1")
    @Order(1)
    public void processMessageTest1() throws IOException {
        File file1 = new File (directoryLocation + "file.txt");
        
        String inputFileName = "file.txt";
        String inputFileDir = "./src/test/resources/";
        String fullPathFile = inputFileDir + inputFileName;
        
        String requestMessageRef = "file";
        String testContent = readFile(fullPathFile, "TestFile");
        String testHeader = "<FileName>" + inputFileName + "</FileName>";
        String testMessage = testHeader + testContent;
        String[] folderStrings = {"some string"};
        
        try {
            ReflectionTestUtils.setField(msg, "messageId", requestMessageRef.getBytes());
            ReflectionTestUtils.setField(msg, "format", CMQC.MQFMT_RF_HEADER_2);
            
            when(rfh2.getStrucLength()).thenReturn(testMessage.getBytes().length);
            when(rfh2.getEncoding()).thenReturn(12000);
            when(rfh2.getCodedCharSetId()).thenReturn(CMQC.MQCCSI_DEFAULT);
            when(rfh2.getFormat()).thenReturn(CMQC.MQFMT_RF_HEADER_2);
            when(rfh2.getFlags()).thenReturn(1);
            when(rfh2.getNameValueCCSID()).thenReturn(1);
            when(rfh2.getFolderStrings()).thenReturn(folderStrings);
            when(msg.getDataLength()).thenReturn(testMessage.getBytes().length);
            //when(msg.messageId).thenReturn(requestMessageRef.getBytes());
            when(mainApp.getNewMessage()).thenReturn(msg);
            when(mainApp.getMQMessageOptions()).thenReturn(gmo);
            when(mainApp.setMessageOptions()).thenReturn(CMQC.MQGMO_PROPERTIES_FORCE_MQRFH2 + CMQC.MQGMO_FAIL_IF_QUIESCING + CMQC.MQGMO_NO_WAIT);
            when(mainApp.getMQQueueManager(queueManagerName)).thenReturn(queueManager);
            when(mainApp.getMQRFH2(msg)).thenReturn(rfh2);      // error appears when this executes
            when(mainApp.toHex(requestMessageRef.getBytes())).thenReturn("message ID");
            
            mainApp.receiveMessage();
            
            // assert statement for test case
        } catch (Exception ex) { ex.printStackTrace(); }
    }
}

The error stack trace is :

I have added 2 comments in the stack trace to help identify which line of code gives the error in java file.

/\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.4.5)

2021-06-02 08:36:42.534  INFO 13581 --- [           main] c.a.u.e.e.filemqApplicationTests   : Starting filemqApplicationTests using Java 15.0.2 on upp1 with PID 13581 (started by uppdev in /home/uppdev/eclipse-workspace/filemq/trunk)
2021-06-02 08:36:42.539 DEBUG 13581 --- [           main] c.a.u.e.e.filemqApplicationTests   : Running with Spring Boot v2.4.5, Spring v5.3.6
2021-06-02 08:36:42.545  INFO 13581 --- [           main] c.a.u.e.e.filemqApplicationTests   : No active profile set, falling back to default profiles: default
2021-06-02 08:36:43.315  INFO 13581 --- [           main] c.a.u.e.e.filemqApplication        : Host [127.0.0.1]
2021-06-02 08:36:43.316  INFO 13581 --- [           main] c.a.u.e.e.filemqApplication        : Channel [SYSTEM.ADMIN.SVRCONN]
2021-06-02 08:36:43.317  INFO 13581 --- [           main] c.a.u.e.e.filemqApplication        : Port [1414]
2021-06-02 08:36:43.699  INFO 13581 --- [           main] o.s.s.c.ThreadPoolTaskScheduler          : Initializing ExecutorService 'taskScheduler'
2021-06-02 08:36:43.756  INFO 13581 --- [           main] c.a.u.e.e.filemqApplicationTests   : Started filemqApplicationTests in 1.815 seconds (JVM running for 6.399)
2021-06-02 08:36:44.005  INFO 13581 --- [   scheduling-1] c.a.u.e.e.filemqApplication        : QueueManagerName [IPMT_QM]
com.ibm.mq.headers.MQDataException: MQJE001: Completion Code '1', Reason '2142'.
    at com.ibm.mq.headers.internal.Header.validate(Header.java:735)
    at com.ibm.mq.headers.internal.Header.read(Header.java:1057)
    at com.ibm.mq.headers.MQRFH2.read(MQRFH2.java:229)
    at com.ibm.mq.headers.internal.Header.read(Header.java:1024)
    at com.ibm.mq.headers.internal.Header.read(Header.java:985)
    at com.ibm.mq.headers.MQRFH2.<init>(MQRFH2.java:128)
    at com..utilities..filemq.filemqApplication.getMQRFH2(filemqApplication.java:230)                 // getMQRFH2(MQMessage msg) <- this line
    at com..utilities..filemq.filemqApplicationTests.sendPosDRSTest(filemqApplicationTests.java:176)  // when(mainApp.getMQRFH2(msg)).thenReturn(rfh2); <- this line
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:564)
    at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:688)
    at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
    at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
    at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:210)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:206)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:131)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:65)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:220)
    at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:188)
    at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:202)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:181)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:128)
    at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invokeAllTests(JUnitPlatformProvider.java:150)
    at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invoke(JUnitPlatformProvider.java:124)
    at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:384)
    at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:345)
    at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:126)
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:418)
Caused by: com.ibm.mq.headers.internal.validator.MQHeaderValidationException: MQHDR0011:Header 'MQRFH2' has an invalid value '
t com.ibm.mq.headers.internal.MQCharField$1.validate(MQCharField.java:181)
    at com.ibm.mq.headers.internal.validator.ChainedValidator.validate(ChainedValidator.java:73)
    at com.ibm.mq.headers.internal.validator.ChainedValidator.validate(ChainedValidator.java:73)
    at com.ibm.mq.headers.internal.HeaderType.validate(HeaderType.java:511)
    at com.ibm.mq.headers.internal.Header.validate(Header.java:729)
    at com.ibm.mq.headers.internal.Header.read(Header.java:1057)
    at com.ibm.mq.headers.MQRFH2.read(MQRFH2.java:229)
    at com.ibm.mq.headers.internal.Header.read(Header.java:1024)
    at com.ibm.mq.headers.internal.Header.read(Header.java:985)
    at com.ibm.mq.headers.MQRFH2.<init>(MQRFH2.java:128)
    at com.utilities.filemq.filemqApplication.getMQRFH2(filemqApplication.java:230)
    at com.utilities.filemq.filemqApplication$MockitoMock$1966099648.getMQRFH2$accessor$sDzBJ9IF(Unknown Source)
    at com.utilities.filemq.filemqApplication$MockitoMock$1966099648$auxiliary$B5FfFFK0.call(Unknown Source)
    at org.mockito.internal.invocation.RealMethod$FromCallable$1.call(RealMethod.java:40)
    at org.mockito.internal.invocation.RealMethod$FromBehavior.invoke(RealMethod.java:62)
    at org.mockito.internal.invocation.InterceptedInvocation.callRealMethod(InterceptedInvocation.java:141)
    at org.mockito.internal.stubbing.answers.CallsRealMethods.answer(CallsRealMethods.java:44)
    at org.mockito.Answers.answer(Answers.java:98)
    at org.mockito.internal.handler.MockHandlerImpl.handle(MockHandlerImpl.java:106)
    at org.mockito.internal.handler.NullResultGuardian.handle(NullResultGuardian.java:29)
    at org.mockito.internal.handler.InvocationNotifierHandler.handle(InvocationNotifierHandler.java:33)
    at org.mockito.internal.creation.bytebuddy.MockMethodInterceptor.doIntercept(MockMethodInterceptor.java:82)
    at org.mockito.internal.creation.bytebuddy.MockMethodInterceptor.doIntercept(MockMethodInterceptor.java:56)
    at org.mockito.internal.creation.bytebuddy.MockMethodInterceptor$DispatcherDefaultingToRealMethod.interceptSuperCallable(MockMethodInterceptor.java:141)
    at com.utilities.filemq.filemqApplication$MockitoMock$1966099648.getMQRFH2(Unknown Source)
    ... 66 more
2021-06-02 08:36:44.048 ERROR 13581 --- [           main] c.a.u.e.e.filemqApplication        : com.ibm.mq.headers.MQDataException: MQJE001: Completion Code '1', Reason '2142'.
2021-06-02 08:36:44.090  INFO 13581 --- [   scheduling-1] c.a.u.e.e.filemqApplication        : QueueName [tch.in.ib.q]
beforeee receive msg creationnn ....
beforeee q getttttttt ....
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 5.319 s - in com.utilities.filemq.filemqApplicationTests
2021-06-02 08:36:44.142  INFO 13581 --- [   scheduling-1] c.a.u.e.e.filemqApplication        : No messages waiting in the queue...
2021-06-02 08:36:44.240  INFO 13581 --- [extShutdownHook] o.s.s.c.ThreadPoolTaskScheduler          : Shutting down ExecutorService 'taskScheduler'

Please help me to identify what's wrong and how to counter it.

As is Evident from the error trace there's the exception : MQDataException

This exception occurs when MQRFH2 has invalid data. But the only problem is I have Mocked MQRFH2 bean so technically it should not give this error.

Thanks

chughts
  • 4,210
  • 2
  • 14
  • 27

2 Answers2

0

It looks like you have messed up the

String[] folderStrings = {"some string"};

folderStrings should be a XML style layout of the mcd, jms and usr (optional) folders.

i.e.

String[] folderStrings = {"<mcd><Msd>jms_text</Msd></mcd>", 
                          "<jms><Dst>queue:///TEST.Q1</Dst><Tms>1622657826783</Tms><Dlv>2</Dlv></jms>",
                          "<usr><MyProp01>somevalue</MyProp01></usr>"};

Why don't you use a real JMS application to create the message you want then code the layout in your mock up program.


Updated June 3, 2021.

Here is a complete MQ/Java program that will create an MQRFH2 message and read the message data from a file.

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Hashtable;

import com.ibm.mq.MQException;
import com.ibm.mq.MQMessage;
import com.ibm.mq.MQPutMessageOptions;
import com.ibm.mq.MQQueue;
import com.ibm.mq.MQQueueManager;
import com.ibm.mq.constants.CMQC;
import com.ibm.mq.headers.MQRFH2;

/**
 * Program Name
 *  MQTest71F
 *
 * Description
 *  This java class will connect to a remote queue manager with the
 *  MQ setting stored in a HashTable and put a JMS message
 * (aka MQRFH2 message) on a queue.  The message data will be read from a file.
 *
 * Sample Command Line Parameters
 *  -m MQA1 -h 127.0.0.1 -p 1414 -c TEST.CHL -q TEST.Q1 -f input_file -u UserID -x Password
 *
 * @author Roger Lacroix
 */
public class MQTest71F
{
   private static final SimpleDateFormat  LOGGER_TIMESTAMP = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");

   private Hashtable<String,String> params;
   private Hashtable<String,Object> mqht;

   /**
    * The constructor
    */
   public MQTest71F()
   {
      super();
      params = new Hashtable<String,String>();
      mqht = new Hashtable<String,Object>();
   }

   /**
    * Make sure the required parameters are present.
    * @return true/false
    */
   private boolean allParamsPresent()
   {
      boolean b = params.containsKey("-h") && params.containsKey("-p") &&
                  params.containsKey("-c") && params.containsKey("-m") &&
                  params.containsKey("-q") && params.containsKey("-f") &&
                  params.containsKey("-u") && params.containsKey("-x");
      if (b)
      {
         try
         {
            Integer.parseInt((String) params.get("-p"));
         }
         catch (NumberFormatException e)
         {
            b = false;
         }
      }

      return b;
   }

   /**
    * Extract the command-line parameters and initialize the MQ HashTable.
    * @param args
    * @throws IllegalArgumentException
    * @throws FileNotFoundException
    */
   private void init(String[] args) throws IllegalArgumentException, FileNotFoundException
   {
      int port = 1414;
      if (args.length > 0 && (args.length % 2) == 0)
      {
         for (int i = 0; i < args.length; i += 2)
         {
            params.put(args[i], args[i + 1]);
         }
      }
      else
      {
         throw new IllegalArgumentException();
      }

      if (allParamsPresent())
      {
         if (!((new File(params.get("-f"))).exists()))
         {
            throw new FileNotFoundException("File not found: " + params.get("-f"));
         }

         try
         {
            port = Integer.parseInt((String) params.get("-p"));
         }
         catch (NumberFormatException e)
         {
            port = 1414;
         }

         mqht.put(CMQC.CHANNEL_PROPERTY, params.get("-c"));
         mqht.put(CMQC.HOST_NAME_PROPERTY, params.get("-h"));
         mqht.put(CMQC.PORT_PROPERTY, new Integer(port));
         mqht.put(CMQC.USER_ID_PROPERTY, params.get("-u"));
         mqht.put(CMQC.PASSWORD_PROPERTY, params.get("-x"));

         // I don't want to see MQ exceptions at the console.
         MQException.log = null;
      }
      else
      {
         throw new IllegalArgumentException();
      }
   }

   /**
    * Connect, open queue, write a message, close queue and disconnect.
    *
    */
   private void testSend()
   {
      String qMgrName = (String) params.get("-m");
      String outputQName = (String) params.get("-q");
      String inputFile = (String) params.get("-f");
      MQQueueManager qMgr = null;
      MQQueue queue = null;
      int openOptions = CMQC.MQOO_OUTPUT + CMQC.MQOO_FAIL_IF_QUIESCING;
      MQPutMessageOptions pmo = new MQPutMessageOptions();

      try
      {
         qMgr = new MQQueueManager(qMgrName, mqht);
         logger("successfully connected to "+ qMgrName);

         queue = qMgr.accessQueue(outputQName, openOptions);
         logger("successfully opened "+ outputQName);

         MQMessage sendmsg = new MQMessage();

         // Set the RFH2 Values
         MQRFH2 rfh2 = new MQRFH2();
         rfh2.setEncoding(CMQC.MQENC_NATIVE);
         rfh2.setCodedCharSetId(CMQC.MQCCSI_INHERIT);
         // Tell MQ what type of data is in the file.  
         // Note: If it is binary then use CMQC.MQFMT_NONE 
         rfh2.setFormat(CMQC.MQFMT_STRING);
         rfh2.setFlags(0);
         rfh2.setNameValueCCSID(1208);

         /**
          * First, set the 'Message Service Domain' value.
          * Valid values for mcd.Msd are:
          * jms_none, jms_text, jms_bytes, jms_map, jms_stream & jms_object
          */
         rfh2.setFieldValue("mcd", "Msd", "jms_text");

         /**
          * Set the destination JMS queue name.
          */
         rfh2.setFieldValue("jms", "Dst", "queue:///"+outputQName);

         /**
          * Set user values.
          */
         rfh2.setFieldValue("usr", "SomeNum", 123);
         rfh2.setFieldValue("usr", "SomeText", "TEST");

         // Set the MQRFH2 structure to the message
         rfh2.write(sendmsg);

         // Read the data from a file then Write message data
         sendmsg.write(readFile(inputFile));

         // Set MQMD values
         sendmsg.messageId = CMQC.MQMI_NONE;
         sendmsg.correlationId = CMQC.MQCI_NONE;
         sendmsg.messageType = CMQC.MQMT_DATAGRAM;
         // IMPORTANT: Set the format to MQRFH2 aka JMS Message.
         sendmsg.format = CMQC.MQFMT_RF_HEADER_2;

         // put the message on the queue
         queue.put(sendmsg, pmo);
         logger("Put MQRFH2 message on queue '" + outputQName + "' with message data from file '" + inputFile+"'");
      }
      catch (MQException e)
      {
         logger("CC=" +e.completionCode + " : RC=" + e.reasonCode);
      }
      catch (IOException e)
      {
         logger("IOException:" +e.getLocalizedMessage());
      }
      finally
      {
         try
         {
            if (queue != null)
            {
               queue.close();
               logger("closed: "+ outputQName);
            }
         }
         catch (MQException e)
         {
            logger("CC=" +e.completionCode + " : RC=" + e.reasonCode);
         }
         try
         {
            if (qMgr != null)
            {
               qMgr.disconnect();
               logger("disconnected from "+ qMgrName);
            }
         }
         catch (MQException e)
         {
            logger("CC=" +e.completionCode + " : RC=" + e.reasonCode);
         }
      }
   }

   /**
    * This method will read a file.
    *
    * @param fileName the name of the file.
    */
   private byte[] readFile(String fileName) throws IOException
   {
      byte[] byteData = null;
      RandomAccessFile in = null;

      try
      {
         in = new RandomAccessFile(fileName, "r");
         long len = in.length();
         int iLen = (int)len;
         byteData = new byte[iLen];

         in.read(byteData);
      }
      finally
      {
         if (in != null)
            in.close();
      }

      return byteData;
   }

   /**
    * A simple logger method
    * @param data
    */
   public static void logger(String data)
   {
      String className = Thread.currentThread().getStackTrace()[2].getClassName();

      // Remove the package info.
      if ( (className != null) && (className.lastIndexOf('.') != -1) )
         className = className.substring(className.lastIndexOf('.')+1);

      System.out.println(LOGGER_TIMESTAMP.format(new Date())+" "+className+": "+Thread.currentThread().getStackTrace()[2].getMethodName()+": "+data);
   }

   /**
    * main line
    * @param args
    */
   public static void main(String[] args)
   {
      MQTest71F write = new MQTest71F();

      try
      {
         write.init(args);
         write.testSend();
      }
      catch (IllegalArgumentException e)
      {
         logger("Usage: java MQTest71F -m QueueManagerName -h host -p port -c channel -q QueueName -f input_file -u UserID -x Password");
         System.exit(1);
      }
      catch (FileNotFoundException e)
      {
         logger(e.getMessage());
         System.exit(1);
      }

      System.exit(0);
   }
}
Roger
  • 7,062
  • 13
  • 20
  • I dont think folderStrings has any problem because the error appears before that statement is executed. If you check the main application code, inside the processMessage() method, getMQRFH2(message) method gives error in the error stack trace. Also, I have executed the testcase after incorporating the changes suggested but it didnt work. – NIkhil Rohilla Jun 03 '21 at 07:09
  • I have found out the problem and solution. Please check my asnwer. – NIkhil Rohilla Jun 04 '21 at 11:37
0

I found the working solution to my problem.

I changed the statement:

when(mainApp.getMQRFH2(msg)).thenReturn(rfh2);

to the following:

Mockito.doReturn(rfh2).when(mainApp).getMQRFH2(msg);

Now the error "MQRFH2 has invalid value" does not appear.

These 2 statements should basically both work but in this case of unit test, only one works.

I have found out that there are some cases in which when().thenReturn() does not work / gives compile time error and for the same case doReturn().when() works completely fine.

The answer I found most helpful is available here. Adrian Shum's answer is very helpful along with Dawood ibn kareem.

There is also one more link to a detailed answer by akcasoy here. He explains with an example how doReturn and when are different with a satisfactory explanation.