31
JUnit Functional test cases By: Prudhvi 25-July-2015

Munit junit test case

Embed Size (px)

Citation preview

Page 1: Munit junit test case

JUnit Functional test casesBy: Prudhvi

25-July-2015

Page 2: Munit junit test case

Abstract

The main theme of this is what the issues to write test cases using JUnit are and how to overcome those issues.

Page 3: Munit junit test case

Contents

1. ABSTRACT2. INTRODUCTION3. PROBLEM STATEMENT4. SOLUTION5. CONCLUSION6. REFERENCE

Page 4: Munit junit test case

IntroductionWe have multiple unit test frameworks to write unit and functional test cases for our services. When we write functional test cases using JUnit we can’t mock mule components. To resolve this issues we have to use MUnit and I am going to explain what is the problem with JUnit and how to resolve using MUnit in the below.

Page 5: Munit junit test case

Problem Statement

When we write functional test cases using JUnit, the test case will directly connect to original components like SAP, Salesforce etc. and insert/select the data. It is the issue in JUnit functional test case why because we are writing functional test cases to check whether entire functionality is working as expected or not without modifying the original components (SAP, Salesforce, Database) data, but in JUnit functional test cases it is directly connecting to original components and modifying the original data.

Page 6: Munit junit test case

Examples:1. SAP ConnectorMule flow:

Page 7: Munit junit test case

Flow of execution

Trigger the service with xml request.Receive the input request and process it.Transform the processed request to SAP IDoc and push it to SAP.

Page 8: Munit junit test case

Functional test case using JUnit:Public void functionalTest(){ File fXmlFile = new File(request.xml);

StringBuilder sb = new StringBuilder();BufferedReader br = new BufferedReader(new FileReader(fXmlFile));

String sCurrentLine = new String();//Read the data from file and append to stringwhile ((sCurrentLine = br.readLine()) != null) {

sb.append(sCurrentLine);}

DefaultHttpClient httpclient = new DefaultHttpClient();

HttpPost httppost = new HttpPost(requrl);

httppost.setEntity(new StringEntity(sb.toString(), "UTF-8"));//Trigger the serviceHttpResponse response = httpclient.execute(httppost);

}

Page 9: Munit junit test case

Flow of execution1. Read the input request from request.xml file.2. Trigger the service with above request.3. Process the input request.4. Transform the processed request to SAP IDoc and push it to

SAP.

IssueHere we are unable to mock the SAP component so the test case is directly pushing the IDoc to original SAP.

NOTE: Not only pushing the IDoc to SAP, at the time of receiving IDoc from SAP also we will face same issue.

Page 10: Munit junit test case

2. SalesforceMule flow

Page 11: Munit junit test case
Page 12: Munit junit test case

Flow of execution1. Trigger the service with xml request.2. Processes the input request.3. Create the processed request as customer in Salesforce.

Page 13: Munit junit test case

Functional Test Case

Public void functionalTest(){ File fXmlFile = new File(request.xml);

StringBuilder sb = new StringBuilder();BufferedReader br = new BufferedReader(new FileReader(fXmlFile));

String sCurrentLine = new String();

// Read the data from file and append to stringwhile ((sCurrentLine = br.readLine()) != null) {

sb.append(sCurrentLine);}

DefaultHttpClient httpclient = new DefaultHttpClient();

HttpPost httppost = new HttpPost(requrl);

httppost.setEntity(new StringEntity(sb.toString(), "UTF-8"));//Trigger the serviceHttpResponse response = httpclient.execute(httppost);

}

Page 14: Munit junit test case

Flow of Execution1. First read the input request from request.xml file.2. Trigger the service with above request.3. Process the input request.4. Create the customer in salesforce.

IssueHere also we are unable to mock the Salesforce component so it will connect to original Salesforce connector and create the customer on it.

Page 15: Munit junit test case

Sample flow<?xml version="1.0" encoding="UTF-8"?> <mule xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns:tracking="http://www.mulesoft.org/schema/mule/ee/tracking" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation" xmlns:spring="http://www.springframework.org/schema/beans" version="EE-3.6.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd http://www.mulesoft.org/schema/mule/ee/tracking http://www.mulesoft.org/schema/mule/ee/tracking/current/mule-tracking-ee.xsd http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd"> <http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="9090" doc:name="HTTP Listener Configuration"/> <flow name="exampleFlow"> <http:listener config-ref="HTTP_Listener_Configuration" path="/" allowedMethods="GET" doc:name="HTTP"/> <set-payload value="#[message.inboundProperties['http.query.params']['url_key']]" doc:name="Set Original Payload"/> <flow-ref name="exampleFlow2" doc:name="exampleFlow2"/> <choice doc:name="Choice"> <when expression="#[flowVars['my_variable'].equals('var_value_1')]"> <set-payload value="#['response_payload_1']" doc:name="Set Response Payload"/> </when> <otherwise> <set-payload value="#['response_payload_2']" doc:name="Set Response Payload"/> </otherwise> </choice> </flow> <flow name="exampleFlow2"> <choice doc:name="Choice"> <when expression="#['payload_1'.equals(payload)]"> <flow-ref name="exampleSub_Flow1" doc:name="exampleSub_Flow1"/> </when> <otherwise> <flow-ref name="exampleSub_Flow2" doc:name="exampleSub_Flow2"/> </otherwise> </choice> </flow> <sub-flow name="exampleSub_Flow1"> <set-variable variableName="my_variable" value="#['var_value_1']" doc:name="my_variable"/> </sub-flow> <sub-flow name="exampleSub_Flow2"> <set-variable variableName="my_variable" value="#['var_value_2']" doc:name="my_variable"/> </sub-flow> </mule>

Page 16: Munit junit test case

Solution

To resolve the above JUnit functional test case issue we have a separate framework called MUnit. MUnit is also one framework which is used to write test cases as same as JUnit, but here in MUnit we can mock all components like SAP, Salesforce, Database etc. So to overcome the above problem we can use MUnit to write functional test cases.

Page 17: Munit junit test case

Example Mocking Salesforce test case using Munitmflow

<?xml version="1.0" encoding="UTF-8"?><mule xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:vm="http://www.mulesoft.org/schema/mule/vm" xmlns:sfdc="http://www.mulesoft.org/schema/mule/sfdc" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation" xmlns:spring="http://www.springframework.org/schema/beans" xmlns:core="http://www.mulesoft.org/schema/mule/core" version="EE-3.4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mulesoft.org/schema/mule/vm http://www.mulesoft.org/schema/mule/vm/current/mule-vm.xsdhttp://www.mulesoft.org/schema/mule/sfdc http://www.mulesoft.org/schema/mule/sfdc/5.0/mule-sfdc.xsdhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsdhttp://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd"> <vm:endpoint exchange-pattern="request-response" path="CREATE_CSTMR_VM" name="CREATE_CSTMR_VM" doc:name="VM"/> <vm:endpoint exchange-pattern="request-response" path="INSERT_PERSON_ACT_VM" name="INSERT_PERSON_ACT_VM" doc:name="VM"/> <flow name="CreateCustomerSFServiceTSFlow1" doc:name="CreateCustomerSFServiceTSFlow1"> <vm:inbound-endpoint exchange-pattern="request-response" ref="CREATE_CSTMR_VM" doc:name="VM"/> <component class="com.vertu.services.ecom.maintaincustmr.processor.CreateCustomerProcessor" doc:name="CreateCustomerProcessor"/> </flow> <flow name="CreateCustomerSFServiceTSFlow2" doc:name="CreateCustomerSFServiceTSFlow2"> <vm:inbound-endpoint exchange-pattern="request-response" ref="INSERT_PERSON_ACT_VM" doc:name="VM"/> <sfdc:create config-ref="ECOM_SALESFORCE_CONNECTOR" type="#[payload.Type]" doc:name="Salesforce"> <sfdc:objects ref="#[payload.Object]"/> </sfdc:create> </flow></mule>

Here we have a Salesforce component to create the customer in Salesforce and return the customer-id as payload. So in functional test case we should mock this component without connecting to original Salesforce.

Page 18: Munit junit test case

How to mock Salesforce component in MUnit functional test caseTo mock Salesforce component, first we should knowEndpoint type.Name of the message processor and namespace of endpoint (from auto-generated XML).The type of payload the endpoint returns.

Mocking above flow Salesforce componentCreate the salesforce response payload.List<Map<String,Object>> l1 = new ArrayList<Map<String,Object>>();Map<String,Object> m1 = new HashMap<Srtring,Object>>();m1.put(“custid”,”1234”);l1.add(m1);Mock the salesforce component and return the above created list as response payload.whenMessageProcessor("create").ofNamespace("sfdc"). thenReturn( muleMessageWithPayload( l1) );

Page 19: Munit junit test case

MUnit functional test case for above flowpublic class MUnitSalesforceStubTest extends FunctionalMunitSuite { /** * The purpose of this method is to define the list of flow * files which will be loaded by Munit test case before executing * Munit test case. Specify multiple flow files as comma * separated XML files. */ @Override protected String getConfigResources() { return "src/main/app/MUnitSFTest.xml"; } /***The purpose of this method is to define the list of flow name which will execute in Munit test case.*/

Page 20: Munit junit test case

protected List<String> getFlowsExcludedOfInboundDisabling(){List<String> list = new ArrayList<String>();list.add("CreateCustomerSFServiceTSFlow2");return list;}/** * The purpose of this method is to flip between mock * and real time interfaces. Return false to Mock * all endpoints in your flow */ @Override public boolean haveToMockMuleConnectors() { return true; }

Page 21: Munit junit test case

/** * Java based Munit test case. Contains mocking and * invocation of flows and assertions. */ @Test public void validateEchoFlow() throws Exception { List<Map<String,Object>> l1 = new ArrayList<Map<String,Object>>();Map<String,Object> m1 = new HashMap<Srtring,Object>>();m1.put(“custid”,”1234”);l1.add(m1); // Mock SFDC outbound endpoint whenMessageProcessor("query").ofNamespace("sfdc").thenReturn( muleMessageWithPayload( l1) );

Page 22: Munit junit test case

// Run the Munit test case by passing a test payload MuleEvent resultEvent = runFlow( " CreateCustomerSFServiceTSFlow1", testEvent(“request”)); // The resultEvent contains response from the VM flow System.out.println( "The flow response is:: " + resultEvent.getMessage().getPayloadAsString() ); // Do any assertion here using Assert.equals() for asserting response // payload } }

Page 23: Munit junit test case

Mocking Database component test case using MUnitMflow:<flow name="CheckAcctIDFlow" doc:name="CheckAcctIDFlow"> <vm:inbound-endpoint exchange-pattern="request-response" ref="FETCH_ACT_GUID_VM1" doc:name="FETCH_ACT_GUID_VM1"/> <logger message="#[message.inboundProperties['ACCT_GUID']]" level="INFO" doc:name="Logger"/> <jdbc-ee:outbound-endpoint exchange-pattern="request-response" queryKey="Get_ACC_ID" queryTimeout="-1" connector-ref="CDMR_JDBC_CONNECTOR" doc:name="Get_ACCT_ID"/> </flow>

• Here we have a database component used to select and return the account-id from database. So we need to mock this component in functional test case.

Page 24: Munit junit test case

Mocking above flow Database component Create the database response payload. List<Map<String,Object>> l1 = new ArrayList<Map<String,Object>>();Map<String,Object> m1 = new HashMap<Srtring,Object>>();m1.put(“accountid”,”1234”);l1.add(m1); Mock the database component and return the above created list as response payload. whenEndpointWithAddress( "jdbc://Get_ACC_ID" ).thenReturn(new DefaultMuleMessage(l1, muleContext ) );

Page 25: Munit junit test case

MUnit functional test case for above flow

public class MUnitSalesforceStubTest extends FunctionalMunitSuite { /** * The purpose of this method is to define the list of flow * files which will be loaded by Munit test case before executing * Munit test case. Specify multiple flow files as comma * separated XML files. */ @Override protected String getConfigResources() { return "src/main/app/MUnitSFTest.xml"; }

Page 26: Munit junit test case

/** * The purpose of this method is to flip between mock * and real time interfaces. Return false to Mock * all endpoints in your flow */ @Override public boolean haveToMockMuleConnectors() { return true; } /** * Java based Munit test case. Contains mocking and * invocation of flows and assertions. */ @Test public void validateEchoFlow() throws Exception { List<Map<String,Object>> l1 = new ArrayList<Map<String,Object>>();Map<String,Object> m1 = new HashMap<Srtring,Object>>();m1.put(“accountid”,”1234”);l1.add(m1);

Page 27: Munit junit test case

// Mock Database outbound endpoint whenEndpointWithAddress( "jdbc://Get_ACC_ID" ).thenReturn(new DefaultMuleMessage(l1, muleContext ) ); // Run the Munit test case by passing a test payload MuleEvent resultEvent = runFlow( " CheckAcctIDFlow ", testEvent(“request”)); // The resultEvent contains response from the VM flow System.out.println( "The flow response is:: " + resultEvent.getMessage().getPayloadAsString() ); // Do any assertion here using Assert.equals() for asserting response // payload } }

Page 28: Munit junit test case

Benefits• Create Java based or Mule flow based unit test cases • Mock endpoints (Salesforce, Database, or SAP etc.) to return

custom payloads for unit testing • Dynamically flip/parameterize Munit test cases to Mock payloads

or use real time interfaces • Support functional unit testing similar to Mule Functional test case • Support Assertion through Spy processors and additionally verify

flows using Message verifiers (introspect payload at different flows for flow navigation)

• Support Asynchronous flow processing and request-response processors

• Mock without custom database or in memory database • Automate test cases using Maven and generate HTML reports

using Surefire plugins

Page 29: Munit junit test case

Conclusion

When we write test cases using JUnit we can’t mock all mule components and the test case will connect to original connectors(SAP, Salesforce). So to overcome this issue we can use MUnit to write test cases effectively.

Page 31: Munit junit test case

About the Author

Prudhvi