Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... ·...
Transcript of Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... ·...
![Page 1: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/1.jpg)
![Page 2: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/2.jpg)
0
1
2
3
4
5
6
7
8
9
10
10.1
10.2
10.3
10.4
10.5
10.6
10.7
11
12
13
13.1
13.2
13.3
13.4
13.5
13.6
TableofContentsIntroduction
Preface
Changesnew
Introduction
Setup
Testcase
Testvariables
Run
Configuration
Endpoints
Validation
Xml
Schema
Json
Xhtml
Plaintext
Binary
Gzip
Xpath
JsonPath
Actions
Send
Receive
Database
Sleep
Java
Timeout
CitrusReferenceGuide
2
![Page 3: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/3.jpg)
13.7
13.8
13.9
13.10
13.11
13.12
13.13
13.14
13.15
13.16
13.17
13.18
13.19
13.20
13.21
13.22
13.23
13.24
13.25
14
15
16
16.1
16.2
16.3
16.4
16.5
16.6
16.7
16.8
Echo
Stoptime
Createvariables
Trace
Transform
Groovy
Fail
Input
Load
Wait
PurgeJMSqueues
Purgechannels
Purgeendpoints
Assert
Catch
Antrun
Manageserver
Stoptimer
Genericaction
Templates
Testbehaviors
Containers
Sequential
Conditional
Parallel
Iterate
Repeat
RepeatOnError
Timer
Custom
CitrusReferenceGuide
3
![Page 4: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/4.jpg)
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
Finally
Jms
Http
HttpWebsockets
Soap
Ftp
Messagechannel
File
Camel
Vertx
Arquillian
Docker
Kubernetes
Ssh
Rmi
Jmx
Cucumber
Zookeeper
Restdocs
Selenium
Endpointcomponent
Endpointadapter
Functions
ValidationMatchers
Datadictionary
Testactors
Testsuite
Metainfo
Messagetracing
CitrusReferenceGuide
4
![Page 5: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/5.jpg)
47
48
48.1
49
49.1
49.2
49.3
49.4
49.5
49.6
49.7
49.8
49.9
49.10
Reporting
Samples
FlightBookingSample
Appendix
Changes2.6
Changes2.5
Changes2.4
Changes2.3
Changes2.2
Changes2.1
Changes2.0
Changes1.4
Changes1.3
Changes1.2
CitrusReferenceGuide
5
![Page 6: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/6.jpg)
CitrusFramework-ReferenceDocumentation
AuthorsChristophDeppisch,MartinMaher
Version2.7.1
Copyright©2017ConSolSoftwareGmbH
www.citrusframework.org
CitrusReferenceGuide
6Introduction
![Page 7: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/7.jpg)
Preface
Integrationtestingcanbeveryhard,especiallywhenthereisnosufficienttoolsupport.UnittestingisflavoredwithfantastictoolsandAPIslikeJUnit,TestNG,EasyMock,Mockitoandsoon.Thesetoolssupportyouinwritingautomatedtests.Atesterwhoisinchargeofintegrationtestingmaylackoftoolsupportforautomatedtestingespeciallywhenitcomestosimulatemessaginginterfaces.
Inatypicalenterpriseapplicationscenariothetestteamhastodealwithdifferentmessaginginterfacesandvarioustransportprotocols.Withoutsufficienttoolsupporttheautomatedintegrationtestingofmessage-basedinteractionsbetweeninterfacepartnersisexhaustingandsometimesbarelypossible.
Thetesterisforcedtosimulateseveralinterfacepartnersinanend-to-endintegrationtest.Thefirstthingthatcomestoourmindismanualtesting.Nodoubtmanualtestingisfast.Inlongtermperspectivemanualtestingistimeconsumingandcausessevereproblemsregardingmaintainabilityastheyareerrorproneandnotrepeatable.
TheCitrusframeworkgivesacompletetestautomationtoolforintegrationtestingofenterpriseapplications.Youcantestyourmessageinterfacestootherapplicationsasclientandserver.EverytimeacodechangeappliesallautomatedCitrustestsensurethestabilityofinterfacesandmessagecommunication.
RegressiontestingandcontinuousintegrationisveryeasyasCitrusfitsintoyourbuildlifecylceasusualJavaunittest.YoucanuseCitruswithJUnitorTestNGinordertointegratewithyourapplicationbuild.
WithpowerfulvalidationcapabilitiesforvariousmessageformatslikeXML,CSVorJSONCitrusisdesignedtoprovidefullyautomatedintegrationtestsforend-to-endusecases.Citruseffectivelycomposescomplexmessagingusecaseswithresponsegeneration,errorsimulation,databaseinteractionandmore.
ThisdocumentationprovidesareferenceguidetoallfeaturesoftheCitrustestframework.Itgivesadetailedpictureofeffectiveintegrationtestingwithautomatedintegrationtestenvironments.Sincethisdocumentisconsideredtobeunderconstruction,pleasedonothesitatetogiveanycommentsorrequeststoususingouruserorsupportmailinglists.
CitrusReferenceGuide
7Preface
![Page 8: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/8.jpg)
What'snewinCitrus2.7?!Citrus2.7isusingJava8!TheCitrussourcesarecompiledwithJava8whichmeansthatfromnowonyouneedatleastJava8runtimetoworkwithCitrus.WiththisJava8baseCitrusisproudtowelcometwonewcrewmembersforsupportingSeleniumandKubernetesintests.Notenoughwehavethefollowingfeaturesincludedinthebox.
Java8
CitrusisnowusingJava8.ThisismainlybecauseweneedtomoveoninusinglatestversionsofSpringFramework,ApacheCamelandsoon.IfyouarestillstuckonJava7youcannotupdateto2.7astheCitrussourcesarecompiledwithJava8.PleasecontactusincaseyoureallycannotupdatetoJava8inyourproject.WecanthinkofaminorbugfixversionwithCitrus2.6basethatstillsupportsJava7runtime.OnthebrightsidewecannowusethefullpowerofLambdaexpressionsandotherJava8featuresinCitruscodebase.
Kubernetessupport
CitrusisnowabletointeractwithKubernetesremoteAPIinordertomanagepods,servicesandotherresourcesontheKubernetesplatform.TheKubernetesclientisbasedontheFabric8JavaclientthatinteractswiththeKubernetesAPIviaRESTservices.SoyoucanaccessKubernetesresourceswithinCitrusinordertochangeorvalidatetheresourcestateforcontainerizedtesting.Thisisveryusefulwhendealingwithcontainerapplicationenvironmentsaspartoftheintegrationtests.PleasestaytunedforblogpostsandtutorialsamplesonhowCitruscanhelpyoutestMicroserviceswithDockerandKubernetes.Thebasicusageisdescribedinsectionkubernetes.
Seleniumsupport
UserinterfaceandbrowsertestinghasnotbeenafocuswithinCitrusintegrationtestinguntilnowthatwecanintegratewiththefamousSeleniumUItestinglibrary.Thankstothegreatcontributionsmadebythecommunity-especiallybyvdsrd@github-wecanuseSeleniumbasedactionsandfeaturesdirectlyinaCitrustestcase.TheCitrusJavaandXMLDSLbothprovidecomfortableaccesstotheSeleniumAPIinordertosimulate
CitrusReferenceGuide
8Changesnew
![Page 9: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/9.jpg)
userinteractionwithinabrowser.ThemixofuserbasedactionsandCitrusmessagingtransportsimulationgivescompletenewwaysofhandlingcomplexintegrationscenarios.ReadmoreaboutthisinchapterSelenium.
Environmentbasedbefore/aftersuite
Youcanenable/disablebeforeandaftersuiteactionsbasedonoptionalenvironmentorsystemproperties.Userscangivepropertynamesorpropertyvaluesthatarecheckedbeforeexecution.Onlyincasetheenvironmentpropertychecksdopasstheactionsareexecutedbefore/afterthetestsuiterun.
WsAddressingheadercustomization
WehaveimprovedtheheadercustomizationoptionswhenusingSOAPWSAddressingfeature.YoucannowoverwritethedefaultWSAddressingheaderspertestactioninadditiontodefiningtheheadersonclientendpointcomponentlevel.
JsonPathdatadictionary
Jsondatadictionarywasbasedonasimpledotnotatedsyntax.NowyoucanalsousemorecomplexJsonPathexpressionsinordertooverwriteelementsinJsonmessagesbasedonthedatadictionarysettingsinCitrus.Readmoreaboutthatinchapterdata-dictionary.
JavaDSLtestbehavior
TestbehaviorsinJavaDSLrepresenttemplatesinXMLDSL.ThebehaviorencapsulatesasetoftestactionstoagroupthatcanbeappliedtomultipleJavaDSLtests.ThisenablesyoutocombinecommontestactionsinJavaDSLwithmorecomfortablereuseoftestactiondefinitions.Seechaptertest-behaviorshowtousethat.
Autoselectmessagetype
DefaultmessagetypeforvalidationtasksinCitrushasbeenXML.BasedonthismessagetypetherespectivemessagevalidatorimplementationappliesforXML,JSON,plaintextandsoon.Youcannowchangethisdefaultmessagetypebysettingasystemproperty(citrus.default.message.type).AlsoCitrusimprovedtheautoselectalgorithmwhenthedefaultmessagetypeisobviouslynotapplicable.WhenamessagearrivesinCitrusthereceivingactiontriestofindoutwhichmessagevalidatorfitsbestaccordingto
CitrusReferenceGuide
9Changesnew
![Page 10: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/10.jpg)
themessagepayload.XMLmessagecontentisautomaticallyidentifiedby<>characters.JSONmessagepayloadsareidentifiedbyor[]charactersforobjectsandarrayrepresentations.ThiswayCitrustriestofindthebestmatchingmessagevalidatorfortheincomingmessage.BeforethatCitrushasalwaysbeenusingthedefaultmessagetypeXML.
Readaboutdifferentmessagevalidatorsinvalidation.
DefaultCucumbersteps
TheCitrusCucumberextensionnowdefinesdefaultstepdefinitionsforHttp,DockerandSelenium.ThesedefaultstepsarereadyforusageinanyCucumberCitrusfeaturespecification.YoucanloadthedefaultstepsasadditionalgluepackagesinyourCucumberoptions.Afterthatyouarereadytogoforusingthedefaultstepsdirectlyinfeaturespecificationfiles.WiththeextensionsyoucanperformDockerandSeleniumcommandsveryeasy.AlsoyoucandescribetheHttpRESTclient-servercommunicationinBDDstyle.Readmoreaboutthisincucumber.
Refactoring
DeprecatedAPIsandclassesthatcoexistedalongtimearenowremoved.Ifyourprojectisusingonofthesedeprecatedclassesyoumayrunintocompiletimeerrors.PleasehavealookattheCitrusAPIJavaDocsanddocumentationinordertofindouthowtousethenewAPIsandclassesthatreplacedtheolddeprecatedstuff.
Bugfixes
Bugsarepartofoursoftwaredevelopersworldandfixingthemispartofyourdailybusiness,too.FindingandsolvingissuesmakesCitrusbettereveryday.ForadetailedlistingofallbugfixespleaserefertothecompletechangeslogofeachreleaseinJIRA(http://www.citrusframework.org/changes-report.html).
CitrusReferenceGuide
10Changesnew
![Page 11: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/11.jpg)
IntroductionNowadaysenterpriseapplicationsusuallycommunicatewithdifferentpartnersoverlooselycoupledmessaginginterfaces.Theinteractionandtheinterfacecontractneedstobetestedinintegrationtesting.
Inatypicalintegrationtestscenarioweneedtosimulatethecommunicationpartnersovervarioustransports.Howcanwetestusecasescenariosthatincludeseveralinterfacepartnersinteractingwitheachother?Howcansomebodyensurethatthesoftwarecomponentsworkcorrectlyregardingtheinterfacecontract?Howcansomebodyrunintegrationtestcasesinanautomatedreproducibleway?Citrustriestoanswerthesequestions!
Overview
Citrusaimstostronglysupportyouinsimulatinginterfacepartnersacrossdifferentmessagingtransports.YoucaneasilyproduceandconsumemessageswithawiderangeofprotocolslikeHTTP,JMS,TCP/IP,FTP,SMTPandmore.Theframeworkisabletobothactasaclientandserver.IneachcommunicationstepCitrusisabletovalidatemessagecontentstowardssyntaxandsemantics.
InadditiontothattheCitrusoffersawiderangeoftestactionstotakecontroloftheprocessflowduringatest(e.g.iterations,systemavailabilitychecks,databaseconnectivity,parallelism,delaying,errorsimulation,scriptingandmanymore).
ThebasicgoalinCitrustestcasesistodescribeawholeusecasescenarioincludingseveralinterfacepartnersthatexchangemanymessageswitheachother.ThecompositionofcomplexmessageflowsinasingletestcasewithseveralteststepsisoneofthemajorfeaturesinCitrus.
ThetestcasedescriptioniseitherdoneinXMLorJavaandcanbeexecutedmultipletimesasautomatedintegrationtest.WithJUnitandTestNGintegrationCitruscaneasilybeintegratedintoyourbuildlifecycleprocess.DuringatestCitrussimulatesallsurroundinginterfacepartners(clientorserver)withoutanycodingeffort.Witheasydefinitionofexpectedmessagecontent(headerandpayload)forXML,CSV,SOAP,JSONorplaintextmessagesCitrusisabletovalidatetheincomingdatatowardssyntaxandsemantics.
CitrusReferenceGuide
11Introduction
![Page 12: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/12.jpg)
Usagescenarios
IfyouareinchargeofanenterpriseapplicationinamessagebasedsolutionwithmessageinterfacestoothersoftwarecomponentsyoushoulduseCitrus.IncaseyourprojectinteractswithothersoftwareoverdifferentmessagingtransportsandincaseyouneedtosimulatetheseinterfacepartnersonclientorserversideyoushoulduseCitrus.Incaseyouneedtocontinuouslycheckthesoftwarestabilitynotonlyonaunittestingbasisbutalsoinanend-to-endintegrationscenarioyoushoulduseCitrus.Bugfixing,releaseorregressiontestingisveryeasywithCitrus.IncaseyouarestrugglingwithcodestabilityandfeeluncomfortableregardingyournextsoftwarereleaseyoushoulddefinitelyuseCitrus.
ThistestsetupistypicalforaCitrususecase.Insuchatestscenariowehaveasystemundertest(SUT)withseveralmessageinterfacestootherapplicationslikeyouwouldhavewithanenterpriseservicebusforinstance.AclientapplicationinvokesservicesontheSUTapplication.TheSUTislinkedtoseveralbackendapplicationsovervariousmessagingtransports(hereSOAP,JMS,andHttp).Interimmessagenotificationsandfinalresponsesaresentbacktotheclientapplication.Thisgeneratesabunchofmessagesthatareexchangedthroughouttheapplicationsinvolved.
IntheautomatedintegrationtestCitrusneedstosendandreceivethosemessagesoverdifferenttransports.Citrustakescareofallinterfacepartners(ClientApplication,Backend1,Backend2,Backend3)andsimulatestheirbehaviorbysendingproperresponsemessagesinordertokeepthemessageflowalive.
Eachcommunicationstepcomeswithmessagevalidationandcomparisonagainstanexpectedmessagetemplate(e.g.XMLorJSONdata).BesidesmessagingactionsCitrusisalsoabletoperformarbitraryothertestactions.Citrusisabletoperformadatabasequerybetweenrequestsasanexample.
CitrusReferenceGuide
12Introduction
![Page 13: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/13.jpg)
TheCitrustestcaserunsfullyautomatedasaJavaapplication.InfactaCitrustestcaseisnothingbutaJUnitorTestNGtestcase.Stepbystepthewholeusecasescenarioisperformedlikeinarealproductionenvironment.TheCitrustestisrepeatableandisincludedintothesoftwarebuildprocess(e.g.usingMavenorANT)likeanormalunittestcasewoulddo.Thisgivesyoufullyautomatedintegrationteststoensureinterfacestability.
ThefollowingreferenceguidewalksthroughallCitruscapabilitiesandshowshowtosetupagreatintegrationtestwithCitrus.
CitrusReferenceGuide
13Introduction
![Page 14: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/14.jpg)
SetupThischapterdiscusseshowtogetstartedwithCitrus.Itdealswiththeinstallationandsetupoftheframework,soyouarereadytostartwritingtestcasesafterreadingthischapter.
UsuallyyouwoulduseCitrusasadependencylibraryinyourproject.InMavenyouwouldjustaddCitrusasatest-scopeddependencyinyourPOM.WhenusingANTyoucanalsorunCitrusasnormalJavaapplicationfromyourbuild.xml.AsCitrustestsarenothingbutnormalunittestsyoucouldalsouseJUnitorTestNGanttaskstoexecutetheCitrustestcases.
ThischapterdescribestheCitrusprojectsetuppossibilities,chooseoneofthemthatfitsbesttoincludeCitrusintoyourproject.
UsingMaven
Citrususeshttp://maven.apache.org/internallyasaprojectbuildtoolandprovidesextendedsupportforMavenprojects.Mavenwilleaseupyourlifeasitmanagesprojectdependenciesandprovidesextendedbuildlifecyclesandconventionsforcompiling,testing,packagingandinstallingyourJavaproject.ThereforeitisrecommendedtousetheCitrusMavenprojectsetup.IncaseyoualreadyuseMavenitismostsuitableforyoutoincludeCitrusasatest-scopeddependency.
AsMavenhandlesallprojectdependenciesautomaticallyyoudonotneedtodownloadanyCitrusprojectartifactsinadvance.IfyouarenewtoMavenpleaserefertotheofficialMavendocumentationtofindouthowtosetupaMavenproject.
UseCitrusMavenarchetype
IfyoustartfromscratchorincaseyouwouldliketohaveCitrusoperatinginaseparateMavenmoduleyoucanusetheCitrusMavenarchetypetocreateanewMavenproject.ThearchetypewillsetupabasicCitrusprojectstructurewithbasicsettingsandfiles.
mvnarchetype:generate-DarchetypeCatalog=http://citrusframework.org
Choosearchetype:1:http://citrusframework.org->citrus-archetype(BasicarchetypeforCitrusintegrationtestproject)Chooseanumber:1
CitrusReferenceGuide
14Setup
![Page 15: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/15.jpg)
DefinevalueforgroupId:com.consol.citrus.samplesDefinevalueforartifactId:citrus-sampleDefinevalueforversion:1.0-SNAPSHOTDefinevalueforpackage:com.consol.citrus.samples
InthesampleaboveweusedtheCitrusarchetypecataloglocatedontheCitrushomepage.CitrusarchetypesarealsoavailableinMavencentralrepository.Socanalsojustuse"mvnarchetype:generate".AsthelistofdefaultarchetypesavailableinMavencentralisverylongyoumightwanttofilterthelistwith"citrus"andyouwillgetjustafewpossibilitiestochoosefrom.
Weloadthearchetypeinformationfrom"http://citrusframework.org"andchoosetheCitrusbasicarchetype.Nowyouhavetodefineseveralvaluesforyourproject:thegroupId,theartifactId,thepackageandtheprojectversion.Afterthatwearedone!MavencreatedaCitrusprojectstructureforuswhichisreadyfortesting.Youshouldseethefollowingbasicprojectfolderstructure.
citrus-sample|+src||+main|||+java|||+resources||+citrus|||+java|||+resources|||+testspom.xml
TheCitrusprojectisabsolutelyreadyfortesting.WithMavenwecanbuild,package,installandtestourprojectrightawaywithoutanyadjustments.Trytoexecutethefollowingcommands:
mvnintegration-testmvnintegration-test-Dtest=MyFirstCitrusTest
NoteIfyouneedadditionalassistanceinsettingupaCitrusMavenprojectpleasevisitourMavensetuptutorialonhttp://www.citrusframework.org/tutorials.html.
AddCitrustoexistingMavenproject
CitrusReferenceGuide
15Setup
![Page 16: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/16.jpg)
IncaseyoualreadyhaveaproperMavenprojectyoucanalsointegrateCitruswithit.JustaddtheCitrusprojectdependenciesinyourMavenpom.xmlasadependencylikefollows.
WeaddCitrusastest-scopedprojectdependencytotheprojectPOM(pom.xml)
<dependency><groupId>com.consol.citrus</groupId><artifactId>citrus-core</artifactId><version>2.7.1</version><scope>test</scope></dependency>
IncaseyouwouldliketousetheCitrusJavaDSLalsoaddthisdependencytotheproject
<dependency><groupId>com.consol.citrus</groupId><artifactId>citrus-java-dsl</artifactId><version>2.7.1</version><scope>test</scope></dependency>
AddthecitrusMavenplugintoyourproject
<plugin><groupId>com.consol.citrus.mvn</groupId><artifactId>citrus-maven-plugin</artifactId><version>2.7.1</version><configuration><author>DonaldDuck</author><targetPackage>com.consol.citrus</targetPackage></configuration></plugin>
NowthatwehaveaddedCitrustoourMavenprojectwecanstartwritingnewtestcaseswiththeCitrusMavenplugin:
mvncitrus:create-test
OnceyouhavewrittentheCitrustestcasesyoucanexecutethemautomaticallyinyourMavensoftwarebuildlifecylce.Thetestswillbeincludedintoyourprojectsintegration-testphaseusingtheMavensurefireplugin.Hereisasamplesurefireconfigurationfor
CitrusReferenceGuide
16Setup
![Page 17: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/17.jpg)
Citrus.
<plugin><artifactId>maven-surefire-plugin</artifactId><version>2.4.3</version><configuration><skip>true</skip></configuration><executions><execution><id>citrus-tests</id><phase>integration-test</phase><goals><goal>test</goal></goals><configuration><skip>false</skip></configuration></execution></executions></plugin>
TheCitrussourcedirectoriesaredefinedastestsourceslikefollows:
<testSourceDirectory>src/it/java</testSourceDirectory><testResources><testResource><directory>src/it/java</directory><includes><include>**</include></includes><excludes><exclude>*.java</exclude></excludes></testResource><testResource><directory>src/it/tests</directory><includes><include>**/*</include></includes><excludes></excludes></testResource></testResources>
NoweverythingissetupandyoucancalltheusualMaveninstallgoal(mvncleaninstall)inordertobuildyourproject.TheCitrusintegrationtestsareexecutedautomaticallyduringthebuildprocess.BesidesthatyoucancalltheMavenintegration-
CitrusReferenceGuide
17Setup
![Page 18: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/18.jpg)
testphaseexplicitlytoexecuteallCitrustestsoraspecifictestbyitsname:
mvnintegration-testmvnintegration-test-Dtest=MyFirstCitrusTest
NoteIfyouneedadditionalassistanceinsettingupaCitrusMavenprojectpleasevisitourMavensetuptutorialonhttp://www.citrusframework.org/tutorials.html.
UsingAnt
Antisaverypopularwaytocompile,test,packageandexecuteJavaprojects.TheApacheprojecthaseffectivelybecomeastandardinbuildingJavaprojects.YoucanrunCitrustestcaseswithAntasCitrusisnothingbutaJavaapplication.ThissectiondescribesthestepstosetupaproperCitrusAntproject.
Preconditions
BeforewestartwiththeCitrussetupbesuretomeetthefollowingpreconditions.Thefollowingsoftwareshouldbeinstalledonyourcomputer,inordertousetheCitrusframework:
Java8orhigher
InstalledJDKplusJAVA_HOMEenvironmentvariablesetupandpointingtoyourJavainstallationdirectory
JavaIDE(optional)
AJavaIDEwillhelpyoutomanageyourCitrusproject(e.g.creatingandexecutingtestcases).YoucanusetheanyJavaIDE(e.g.EclipseorIntelliJIDEA)butalsoanyconvenientXMLEditortowritenewtestcases.
Ant1.8orhigher
Ant(http://ant.apache.org/)willruntestsandcompileyourCitruscodeextensionsifnecessary.
Download
FirstofallweneedtodownloadthelatestCitrusreleasearchivefromtheofficialwebsitehttp://www.citrusframework.org
CitrusReferenceGuide
18Setup
![Page 19: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/19.jpg)
Citruscomestoyouasazippedarchiveinoneofthefollowingpackages:
citrus-x.x-releasecitrus-x.x-src
ThereleasepackageincludestheCitrusbinariesaswellasthereferencedocumentationandsomesampleapplications.
IncaseyouwanttogetintouchwithdevelopinganddebuggingCitrusyoucanalsogowiththesourcearchivewhichgivesyouthecompleteCitrusJavacodesources.ThewholeCitrusprojectisalsoaccessibleforyouonhttp://github.com/christophd/citrus.ThisopengitrepositoryonGitHubenablesyoutobuildCitrusfromscratchwithMavenandcontributecodechanges.
Installation
AfterdownloadingtheCitrusarchivesweextractthoseintoanappropriatelocationonthelocalstorage.WeareseekingfortheCitrusprojectartifactscomingasnormalJavaarchives(e.g.citrus-core.jar,citrus-ws.jar,etc.)
YouhavetoincludethoseCitrusJavaarchivesaswellasalldependencylibrariestoyourApacheAntJavaclasspath.Usuallyyouwouldcopyalllibrariesintoyourproject'slibdirectoryanddeclarethoselibrariesintheAntbuildfile.AsthisapproachcanbeverytimeconsumingIrecommendtouseadependencymanagementAPIsuchasApacheIvywhichgivesyouautomaticdependencyresolutionlikethatfromMaven.Inparticularthiscomesinhandywithallthe3rdpartydependenciesthatwouldberesolvedautomatically.
NomatterwhatapproachyouareusingtosetuptheApacheAntclasspathseethefollowingsampleAntbuildscriptwhichusestheCitrusprojectartifactsincombinationwiththeTestNGAnttaskstorunthetests.
<projectname="citrus-sample"basedir="."default="citrus.run.tests"xmlns:artifact="antlib:org.apache.maven.artifact.ant"
<propertyfile="src/it/resources/citrus.properties"/>
<pathid="maven-ant-tasks.classpath"path="lib/maven-ant-tasks-2.1.3.jar"/><typedefresource="org/apache/maven/artifact/ant/antlib.xml"uri="antlib:org.apache.maven.artifact.ant"classpathref="maven-ant-tasks.classpath"/>
<artifact:pomid="citrus-pom"file="pom.xml"/><artifact:dependenciesfilesetId="citrus-dependencies"pomRefId="citrus-pom"/>
CitrusReferenceGuide
19Setup
![Page 20: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/20.jpg)
<pathid="citrus-classpath"><pathelementpath="src/it/java"/><pathelementpath="src/it/resources"/><pathelementpath="src/it/tests"/><filesetrefid="citrus-dependencies"/></path>
<taskdefresource="testngtasks"classpath="lib/testng-6.8.8.jar"/>
<targetname="compile.tests"><javacsrcdir="src/it/java"classpathref="citrus-classpath"/><javacsrcdir="src/it/tests"classpathref="citrus-classpath"/></target>
<targetname="create.test"description="Createsanewemptytestcase"><inputmessage="Entertestname:"addproperty="test.name"/><inputmessage="Entertestdescription:"addproperty="test.description"/><inputmessage="Enterauthor'sname:"addproperty="test.author"defaultvalue="$default.test.author"<inputmessage="Enterpackage:"addproperty="test.package"defaultvalue="$default.test.package"<inputmessage="Enterframework:"addproperty="test.framework"defaultvalue="testng"/>
<javaclassname="com.consol.citrus.util.TestCaseCreator"><classpathrefid="citrus-classpath"/><argline="-name$test.name-author$test.author-description$test.description-package$test.package-framework$test.framework"</java></target>
<targetname="citrus.run.tests"depends="compile.tests"description="RunsallCitrustests"<testngclasspathref="citrus-classpath"><classfilesetdir="src/it/java"includes="**/*.class"/></testng></target>
<targetname="citrus.run.single.test"depends="compile.tests"description="Runsasingletestbyname"<touchfile="test.history"/><loadpropertiessrcfile="test.history"/>
<echomessage="Lasttestexecuted:$last.test.executed"/><inputmessage="Entertestnameorleaveemptyforlasttestexecuted:"addproperty="testclass"
<propertyfilefile="test.history"><entrykey="last.test.executed"type="string"value="$testclass"/></propertyfile>
<testngclasspathref="citrus-classpath"><classfilesetdir="src/it/java"includes="**/$testclass.class"/></testng></target>
</project>
CitrusReferenceGuide
20Setup
![Page 21: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/21.jpg)
NoteIfyouneeddetailedassistanceforbuildingCitruswithAntdoalsovisitourtutorialssectiononhttp://www.citrusframework.org.ThereyoucanfindatutorialwhichdescribestheCitrusJavaprojectsetupwithAntfromscratch.
CitrusReferenceGuide
21Setup
![Page 22: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/22.jpg)
TestcasesNowletusstartwritingtestcases!AtestcaseinCitrusdescribesallstepsforacertainusecaseinonesinglefile.TheCitrustestholdsasequenceoftestactions.Eachactionrepresentsaveryspecialpurposesuchassendingorreceivingamessage.Typicallywithmessage-basedenterpriseapplicationsthesendingandreceivingofmessagesrepresentthemainactionsinsideatest.
HoweveryouwilllearnthatCitrusismorethanjustasimpleSOAPclientforinstance.Eachtestcasecanholdcomplexactionssuchasconnectingtothedatabase,transformingdata,addingloopsandconditionalsteps.WiththedefaultCitrusactionsetyoucanaccomplishverycomplexusecaseintegrationtests.Laterinthisguidewewillbrieflydiscussallavailabletestactionsandlearnhowtousevariousmessagetransportswithinthetest.Fornowwewillconcentrateonthebasictestcasestructure.
ThefigureabovedescribesatypicaltestactionsequenceinCitrus.Alistofsendingandreceivingtestactionscomposingatypicaltestcasehere.EachactionreferencesapredefinedCitrusendpointcomponentthatwearegoingtotalkaboutlateron.
Sohowdowedefinethosetestcases?IngeneralCitrusspecifiestestcasesasJavaclasses.WithTestNGorJUnityoucanexecutetheCitrustestswithinyourJavaruntimeasyouwoulddowithinunittesting.YoucancodetheCitrustestinasingleJavaclass
CitrusReferenceGuide
22Testcase
![Page 23: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/23.jpg)
doingassertionsandusingSpring'sdependencyinjectionmechanisms.
IfyouarenotfamiliartowritingJavacodeyoucanalsowriteCitrustestsasXMLfiles.WhatevertestlanguageyouchooseforCitrusthewholetestcasedescriptiontakesplaceinonesinglefile(JavaorXML).ThischapterwillintroducethecustomXMLschemalanguageaswellastheJavadomainspecificlanguagesoyouwillbeabletowriteCitrustestcasesnomatterwhatknowledgebaseyoubelongto.
WritingtestcasesinXML
Putsimply,aCitrustestcaseisnothingbutasimpleSpringXMLconfigurationfile.TheSpringframeworkhasbecomeastateoftheartdevelopmentframeworkforenterpriseJavaapplications.AsyouworkwithCitrusyouwillalsolearnhowtousetheSpringIoc(Inversionofcontrol)containerandtheconceptsofdependencyinjection.SoletushavealookatthepureSpringXMLconfigurationsyntaxfirst.YouarefreetowritefullycompatibletestcasesfortheCitrusframeworkjustusingthissyntax.
Springbeandefinitionsyntax
<beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd">
<beanname="MyFirstTest"class="com.consol.citrus.TestCase"><propertyname="variableDefinitions"><!--variablesofthistestgohere--></property><propertyname="actions"><!--actionsofthistestgohere--></property></bean></beans>
CitruscanexecutetheseSpringbeandefinitionsasnormaltestcases-noproblem,butthepureSpringXMLsyntaxisveryverboseandprobablynotthebestwaytodescribeatestcaseinCitrus.InparticularyouhavetoknowalotofCitrusinternalssuchasJavaclassnamesandpropertynames.Inadditiontothatastestscenariosgetmorecomplexthetestcasesgrowinsize.Soweneedamoreeffectiveandcomfortablewayofwritingtests.ThereforeCitrusprovidesacustomXMLschemadefinitionforwritingtestcaseswhichismuchmoreadequateforourtestingpurpose.
CitrusReferenceGuide
23Testcase
![Page 24: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/24.jpg)
ThecustomXMLschemaaimstoreachtheconvenienceofdomainspecificlanguages(DSL).LetushavealookattheCitrustestdescribingXMLlanguagebyintroducingafirstverysimpletestcasedefinition:
XMLDSL
<spring:beansxmlns="http://www.citrusframework.org/schema/testcase"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:spring="http://www.springframework.org/schema/beans"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.citrusframework.org/schema/testcasehttp://www.citrusframework.org/schema/testcase/citrus-testcase.xsd">
<testcasename="MyFirstTest"><description>Firstexampleshowingthebasictestcasedefinitionelements!</description><variables><variablename="text"value="HelloTestFramework"/></variables><actions><echo><message>$text</message></echo></actions></testcase></spring:beans>
Wedoneedthe<spring:beans>rootelementastheXMLfileisreadbytheSpringIoCcontainer.InsidethisrootelementtheCitrusspecificnamespacedefinitionstakeplace.
Thetestcaseitselfgetsamandatorynamethatmustbeuniquethroughoutalltestcasesinaproject.Youwillreceiveerrorswhenusingduplicatetestnames.ThetestnamehastofollowthecommonJavanamingconventionsandrulesforJavaclasses.Thismeansnamesmustnotcontainanywhitespacecharactersbutcharacterslike'-','.','_'aresupported.Forexample,TestFeature_1isvalidbutTestFeature1isnotasitcontainswhitespacecharacterslikespaces.
NowthatwehaveanXMLdefinitionthatdescribesthestepsofourtestweneedaJavaexecutableforthetest.TheJavaexecutableisneededfortheframeworkinordertorunthetest.SeethefollowingsampleJavaclassthatrepresentsasimpleCitrusJavatest:
importorg.testng.annotations.Test;
CitrusReferenceGuide
24Testcase
![Page 25: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/25.jpg)
importcom.consol.citrus.annotations.CitrusTest;importcom.consol.citrus.testng.AbstractTestNGCitrusTest;
@TestpublicclassMyFirstTestextendsAbstractTestNGCitrusTest
@CitrusXmlTest(name="MyFirstTest")publicvoidmyFirstTest()
ThesampleaboveisaJavaclassthatrepresentsavalidCitrusJavaexecutable.TheJavaclasshasnoprogramminglogicasweuseaXMLtestcasehere.TheJavaclasscanalsobegeneratedusingtheCitrusMavenplugin.TheJavaclassextendsfrombasicsuperclassAbstractTestNGCitrusTestandthereforeusesTestNGasunittestframework.CitrusalsosupportsJUnitasunittestframework.Readmoreaboutthisinrun-testngandrun-junit.
UptonowitisimportanttounderstandthatCitrusalwaysneedsaJavaexecutabletestclass.IncaseweusetheXMLtestrepresentationtheJavapartisgeneric,canbegeneratedandcontainsnoprogramminglogic.TheXMLtestdefinesallstepsandisourprimarytestcasedefinition.
WritingtestcasesinJava
BeforewegointomoredetailsontheattributesandactionsthattakeplacewithinatestcasewejusthavealookathowtowritetestcaseswithpureJavacode.CitrusworkswithJavaandusesthewellknownJUnitandTestNGframeworkbenefitsthatyoumaybeusedtoasatester.ManyusersmayprefertowriteJavacodeinsteadoftheverboseXMLsyntax.ThereforeyouhaveanotherpossibilityforwritingCitrustestsinpureJava.
WhenusingtheCitrusJavaDSLweneedtoincludeaspecialMavendependencymoduletoourprojectthatprovidestheneededAPI.
<dependency><groupId>com.consol.citrus</groupId><artifactId>citrus-java-dsl</artifactId><version>2.7.1</version><scope>test</scope></dependency>
CitrusingeneraldifferencesbetweentwowaysoftestcasesinJava.Thesearetest-designersandtest-runnersthatwedealwitheachinthenexttwosections.
CitrusReferenceGuide
25Testcase
![Page 26: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/26.jpg)
JavaDSLtestdesigner
ThefirstwayofdefiningaCitrustestinJavaisthetest-designer.TheJavaDSLforatestdesignerworkssimilartotheXMLapproach.Thewholetestcaseisbuiltwithalltestactionsfirst.ThenthewholetestcaseisexecutedasawholeCitrustest.ThisishowtodefineaCitrustestwithdesignerJavaDSLmethods:
JavaDSLdesigner
importorg.testng.annotations.Test;importcom.consol.citrus.annotations.CitrusTest;importcom.consol.citrus.dsl.testng.TestNGCitrusTestDesigner;
@TestpublicclassMyFirstTestDesignerextendsTestNGCitrusTestDesigner@CitrusTest(name="MyFirstTest")publicvoidmyFirstTest()description("Firstexampleshowingthebasictestcasedefinitionelements!");
variable("text","HelloTestFramework");
echo("$text");
CitrusprovidesabaseJavaclasscom.consol.citrus.dsl.testng.TestNGCitrusTestDesignerthatprovidesallcapabilitiesforyouinformofbuilderpatternmethods.Justusethe@CitrusTestannotationontopofthetestmethod.Citruswillusethemethodnameasthetestnamebydefault.Asyoucanseeintheexampleaboveyoucanalsocustomizethetestnamewithinthe@CitrusTestannotation.Thetestmethodbuildsalltestactionsusingthetestbuilderpattern.Thedefinedtestactionswillthenbecalledlateronduringtestruntime.
Thedesigntimeruntimedifferenceintest-designerisreallyimportanttobeunderstood.YoucanmixtheCitrusJavaDSLexecutionwithotherJavacodewithcertainlimitations.Wewillexplainthislateronwhenintroducingthetest-runner.
ThisisthebasictestJavaclasspatternusedinCitrus.Youasatesterwithdevelopmentbackgroundcaneasilyextendthispatternforcustomizedlogic.AgainifyouarecomingwithoutcodingexperiencedonotworrythisJavacodeisoptional.YoucandoexactlythesamewiththeXMLsyntaxonlyasshownbefore.ThetestdesignerJavaDSLismuchmorepowerfulthoughasyoucanusethefullJavaprogramminglanguagewithclassinheritanceandmethoddelegation.
CitrusReferenceGuide
26Testcase
![Page 27: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/27.jpg)
Wehavementionedthatthetest-designerwillbuildthecompletetestcaseindesigntimewithallactionsfirstbeforeexecutionofthewholetestcasetakesplaceatruntimeofthetest.ThisapproachhastheadvantagethatCitrusknowsalltestactionsinatestbeforeexecution.OntheotherhandyouarelimitedinmixingJavaDSLmethodcallsandnormalJavacode.Thefollowingexampleshouldclarifythingsalittlebit.
JavaDSLdesigner
importorg.testng.annotations.Test;importcom.consol.citrus.annotations.CitrusTest;importcom.consol.citrus.dsl.testng.TestNGCitrusTestDesigner;
@TestpublicclassLoggingTestDesignerextendsTestNGCitrusTestDesignerprivateLoggingServiceloggingService=newLoggingService();
@CitrusTest(name="LoggingTest")publicvoidloggingTest()echo("BeforeloggingServicecall");
loggingService.log("Nowcalledcustomloggingservice");
echo("AfterloggingServicecall");
InthisexampletestcaseaboveweuseaninstanceofacustomLoggingServiceandcallsomeoperationlog()inthemiddleofourJavaDSLtest.NowdevelopersmightexpecttheloggingservicecalltobedoneinthemiddleoftheJavaCitrustestcasebutifwehavealookattheloggingoutputofthetestwegetatotaldifferentresult:
Expectedoutput
INFOCitrus|STARTINGTESTLoggingTestINFOEchoAction|BeforeloggingServicecallINFOLoggingService|NowcalledcustomloggingserviceINFOEchoAction|AfterloggingServicecallINFOCitrus|TESTSUCCESSLoggingTest
Actualoutput
INFOLoggingService|NowcalledcustomloggingserviceINFOCitrus|STARTINGTESTLoggingTestINFOEchoAction|BeforeloggingServicecallINFOEchoAction|AfterloggingServicecall
CitrusReferenceGuide
27Testcase
![Page 28: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/28.jpg)
INFOCitrus|TESTSUCCESSLoggingTest
SoifweanalysetheactualloggingoutputweseethattheloggingservicewascalledevenbeforetheCitrustestcasedidstartitsaction.Thisistheresultoftest-designerbuildingupthewholetestcasefirst.Thedesignercollectsalltestactionsfirstininternalmemorycacheandtheexecutesthewholetestcase.SothecustomservicecallontheLoggingServiceisnotpartoftheCitrusJavaDSLtestandthereforeisexecutedimmediatelyatdesigntime.
Wecanfixthiswiththefollowingtest-designercode:
JavaDSLdesigner
importorg.testng.annotations.Test;importcom.consol.citrus.annotations.CitrusTest;importcom.consol.citrus.dsl.testng.TestNGCitrusTestDesigner;
@TestpublicclassLoggingTestDesignerextendsTestNGCitrusTestDesignerprivateLoggingServiceloggingService=newLoggingService();
@CitrusTest(name="LoggingTest")publicvoidloggingTest()echo("BeforeloggingServicecall");
action(newAbstractTestAction()doExecute(TestContextcontext)loggingService.log("Nowcalledcustomloggingservice"););
echo("AfterloggingServicecall");
NowweplacedtheloggingServicecallinsideacustomTestActionimplementationandthereforethispieceofcodeispartoftheCitrusJavaDSLandfollowingfromthatpartoftheCitrustestexecution.Nowwiththatfixwegettheexpectedloggingoutput:
INFOCitrus|STARTINGTESTLoggingTestINFOEchoAction|BeforeloggingServicecallINFOLoggingService|NowcalledcustomloggingserviceINFOEchoAction|AfterloggingServicecallINFOCitrus|TESTSUCCESSLoggingTest
CitrusReferenceGuide
28Testcase
![Page 29: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/29.jpg)
NowthisisnoteasytounderstandandpeopledidstrugglewiththisseparationofdesigntimeandruntimeofaCitrusJavaDSLtest.ThisiswhywehaveimplementedanewJavaDSLbaseclasscalledtest-runnerthatwedealwithinthenextsection.Beforewecontinuewehavetomentionthatthetest-designerapproachdoesalsoworkforJUnit.AlthoughwehaveonlyseenTestNGsamplecodeinthissectioneverythingisworkingexactlythesamewaywithJUnitframework.Justusethebaseclasscom.consol.citrus.dsl.junit.JUnit4CitrusTestDesignerinstead.
ImportantNeitherTestNGCitrusTestDesignernorJUnit4CitrusTestDesignerimplementationisthreadsafeforparalleltestexecution.Thisissimplybecausethebaseclassisholdingstatetothecurrenttestdesignerinstanceinordertodelegatemethodcallstothisinstance.Thereforeparalleltestmethodexecutionisnotavailable.Fortunatelywehaveaddedathreadsafebaseclassimplementationthatusesresourceinjection.Readmoreaboutthisintestcase-resource-injection.
JavaDSLtestrunner
Thenewtestrunnerconceptsolvestheissuesthatmaycomealongwhenworkingwiththetestdesigner.Wehavealreadyseenasimpleexamplewherethetestdesignerrequiresstrictseparationofdesigntimeandruntime.Thetestrunnerimplementationexecuteseachtestactionimmediately.ThischangestheprerequisitesinsuchthatthetestactionJavaDSLmethodcallscanbemixedwithusualJavacodestatements.Thetheexamplethatwehaveseenbeforeinatestrunnerimplementation:
JavaDSLrunner
importorg.testng.annotations.Test;importcom.consol.citrus.annotations.CitrusTest;importcom.consol.citrus.dsl.testng.TestNGCitrusTestRunner;
@TestpublicclassLoggingTestRunnerextendsTestNGCitrusTestRunnerprivateLoggingServiceloggingService=newLoggingService();
@CitrusTest(name="LoggingTest")publicvoidloggingTest()echo("BeforeloggingServicecall");
loggingService.log("Nowcalledcustomloggingservice");
echo("AfterloggingServicecall");
CitrusReferenceGuide
29Testcase
![Page 30: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/30.jpg)
WiththenewtestrunnerimplementationasbaseclassweareabletomixJavaDSLmethodcallsandnormalJavacodestatementinourtestinanunlimitedway.ThisexampleabovewillalsocreatetheexpectedloggingoutputasallJavaDSLmethodcallsareexecutedimmediately.
INFOCitrus|STARTINGTESTLoggingTestINFOEchoAction|BeforeloggingServicecallINFOLoggingService|NowcalledcustomloggingserviceINFOEchoAction|AfterloggingServicecallINFOCitrus|TESTSUCCESSLoggingTest
Incontrarytothetestdesignerthetestrunnerimplementationwillnotbuildthecompletetestcasebeforeexecution.EachtestactionisexecutedimmediatelyasitiscalledwithJavaDSLbuildermethods.Thiscreatesamorenaturalwayofcodingtestcasesasyouarealsoabletouseiterations,trycatchblocks,finallysectionsandsoon.
IntheexampleshereTestNGwasusedasunitframework.OfcoursetheexactsameapproachcanalsoapplytoJUnitframework.Justusethebaseclasscom.consol.citrus.dsl.junit.JUnit4CitrusTestRunnerinstead.Feelfreetochoosethebaseclassfortest-designerortest-runnerasyoulike.Youcanalsomixthosetwoapproachesinyourproject.CitrusisabletohandlebothwaysofJavaDSLcodeinaproject.
ImportantTheTestNGCitrusTestRunnerandJUnit4CitrusTestRunnerimplementationisnotthreadsafeforparalleltestexecution.Thisissimplybecausethebaseclassisholdingstatetothecurrenttestrunnerinstanceinordertodelegatemethodcallstothisinstance.Thereforeparalleltestmethodexecutionisnotavailable.Fortunatelywehaveaddedathreadsafebaseclassimplementationthatusesresourceinjection.Readmoreaboutthisintestcase-resource-injection.
Designer/Runnerinjection
Intheprevioussectionswehaveseenthedifferentapproachesfortestdesignerandrunnerimplementations.Uptonowthedecisionwhichimplementationtousewasmadebyextendingoneofthebaseclasses:
com.consol.citrus.dsl.testng.TestNGCitrusTestRunnercom.consol.citrus.dsl.testng.TestNGCitrusTestDesignercom.consol.citrus.dsl.junit.JUnit4CitrusTestRunnercom.consol.citrus.dsl.junit.JUnit4CitrusTestDesigner
CitrusReferenceGuide
30Testcase
![Page 31: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/31.jpg)
ThesefourclassesrepresentthedifferentdesignerandrunnerimplementationsforTestNGorJUnit.NowCitrusalsoprovidesaresourceinjectionmechanismforbothdesignerandrunnerimplementations.Theclassesusingthisfeatureare:
com.consol.citrus.dsl.testng.TestNGCitrusTestcom.consol.citrus.dsl.junit.JUnit4CitrusTest
Sowhatisthedealwiththat?Itissimplewhenlookingatafirstexampleusingresourceinjection:
@TestpublicclassInjectionTestextendsJUnit4CitrusTest
@CitrusTest(name="JUnit4DesignerTest")publicvoiddesignerTest(@CitrusResourceTestDesignerdesigner)designer.echo("Nowworkingondesignerinstance");
@CitrusTest(name="JUnit4RunnerTest")publicvoidrunnerTest(@CitrusResourceTestRunnerrunner)runner.echo("Nowworkingonrunnerinstance");
ThedesignerorrunnerinstanceisinjectedasCitrusresourcetothetestmethodasparameter.Thiswaywecanmixdesignerandrunnerinasingletest.Butthisisnottherealmotivationfortheresourceinjection.Theclearadvantageofthisapproachwithinjecteddesignerandrunnerinstancesissupportformultithreading.IncaseyouwanttoexecutetheCitrustestsinparallelusingmultiplethreadsyouneedtousethisapproach.Thisisbecausetheusualdesignerandrunnerbaseclassesarenotthreadsafe.ThisJUnit4CitrusTestbaseclassisbecausetheresourcesinjectedarenotkeptasstateinthebaseclass.
ThisisourfirstCitrusresourceinjectionusecase.Theframeworkisabletoinjectotherresources,too.Findoutmoreaboutthisinthenextsections.
Testcontextinjection
WhenrunningatestcaseinCitruswemakeuseofbasicframeworkcomponentsandcapabilities.Oneofthesecapabilitiesistousetestvariables,functionsandvalidationmatchers.Uptothispointwehavenotlearnedaboutthesethings.Theywillbedescribedintheupcomingchaptersandsectionsinmoredetail.RightnowIwanttotalkaboutresourceinjectioninCitrus.
CitrusReferenceGuide
31Testcase
![Page 32: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/32.jpg)
AllthesefeaturementionedaboveareboundtosomeimportantCitruscomponent:theCitrustestcontext.Thetestcontextholdsallvariablesandisabletoresolvefunctionsandmatchers.Ingeneralyouasatesterwillnotneedexplicitaccesstothiscomponentastheframeworkisworkingwithitbehindthescenes.IncaseyouneedsomeaccessforadvancedoperationswiththeframeworkCitrusprovidesaresourceinjection.Letshavealookatthissothingsaregettingmoreclear.
publicclassResourceInjectionITextendsJUnit4CitrusTestDesigner
@Test@CitrusTestpublicvoidresourceInjectionIT(@CitrusResourceTestContextcontext)context.setVariable("myVariable","somevalue");echo("$myVariable");
Asyoucanseewehaveaddedamethodparameteroftypecom.consol.citrus.context.TestContexttothetestmethod.Theannotation@CitrusResourcetellsCitrustoinjectthisparameterwiththeaccordinginstanceoftheobjectforthistest.Nowwehaveeasyaccesstothecontextandallitscapabilitiessuchasvariablemanagement.
OfcoursethesameapproachworkswithTestNG,too.AsTestNGalsoprovidesresourceinjectionmechanismswehavetomakesurethatthedifferentresourceinjectionapproachesdonotinterferewitheachother.SowetellTestNGtonotinjectthisparameterbydeclaringitas@OptionalforTestNG.InadditiontothatweneedtointroducetheparametertoTestNGwiththe@Parametersannotation.OtherwiseTestNGwouldcomplainaboutnotknowingthisparameter.ThefinaltestmethodwithCitrusresourceinjectionlookslikefollows:
publicclassResourceInjectionITextendsTestNGCitrusTestDesigner
@Test@Parameters("context")@CitrusTestpublicvoidresourceInjectionIT(@Optional@CitrusResourceTestContextcontext)context.setVariable("myVariable","somevalue");echo("$myVariable");
CitrusReferenceGuide
32Testcase
![Page 33: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/33.jpg)
Somemoreannotationsneededbuttheresultisthesame.WehaveaccesstotheCitrustestcontext.OfcourseyoucancombinetheresourceinjectionfordifferentCitruscomponents.Justaddmoresome@CitrusResourceannotatedmethodparameterstothetestmethod.
JavaDSLtestbehaviors
WhenusingtheJavaDSLtheconceptofbehaviorsisagoodwaytoreusetestactionblocks.Byputtingtestactionstoatestbehaviorwecaninstantiateandapplythebehaviortodifferenttestcasesmultipletimes.Themechanismisexplainedbestwhenhavingasimplesample:
publicclassFooBehaviorextendsAbstractTestBehaviorpublicvoidapply()variable("foo","test");
echo("fooBehavior");
publicclassBarBehaviorextendsAbstractTestBehaviorpublicvoidapply()variable("bar","test");
echo("barBehavior");
Thelistingaboveshowstwotestbehaviorsthataddveryspecifictestactionsandtestvariablestothetestcase.AsyoucanseethetestbehaviorisabletousethesameJavaDSLactionmethodsasanormaltestcasewoulddo.Insidetheapplymethodblockwedefinethebehaviorstestlogic.Nowoncethisisdonewecanusethebehaviorsinatestcaselikethis:
@CitrusTestpublicvoidbehaviorTest()description("ThisisabehaviorTest");author("Christoph");status(TestCaseMetaInfo.Status.FINAL);
variable("var","test");
applyBehavior(newFooBehavior());
echo("Successfullyappliedbarbehavior");
CitrusReferenceGuide
33Testcase
![Page 34: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/34.jpg)
applyBehavior(newBarBehavior());
echo("Successfullyappliedbarbehavior");
ThebehaviorisappliedtothetestcasebycallingtheapplyBehaviormethod.Asaresultthebehavioriscalledaddingitslogicatthispointofthetestexecution.Thesamebehaviorcannowbecalledinmultipletestcasessowehaveareusablesetoftestactions.
Description
Inthetestexamplesthatwehaveseensofaryoumayhavenoticedthatatestercangiveadetailedtestdescription.Thetestcasedescriptionclarifiesthetestingpurposeandperspectives.Thedescriptionshouldgiveashortintroductiontotheintendedusecasescenariothatwillbetested.Theusershouldgetafirstimpressionwhatthetestcaseisallaboutaswellasspecialinformationtounderstandthetestscenario.Youcanusefreetextinyourtestdescriptionnolimittothenumberofcharacters.ButbeawareoftheXMLvalidationrulesofwellformedXMLwhenusingtheXMLtestsyntax(e.g.specialcharacterescaping,useofCDATAsectionsmayberequired)
TestActions
Nowwegetclosetothemainpartofwritinganintegrationtest.ACitrustestcasedefinesasequenceofactionsthatwilltakeplaceduringthetest.Actionsbydefaultareexecutedsequentiallyinthesameorderastheyaredefinedinthetestcasedefinition.
XMLDSL
<actions><action>[...]</action><action>[...]</action></actions>
Allactionshaveindividualnamesandpropertiesthatdefinetherespectivebehavior.Citrusoffersawiderangeoftestactionsfromscratch,butyouarealsoabletowriteyourowntestactionsinJavaorGroovyandexecutethemduringatest.actionsgivesyouabriefdescriptionofallavailableactionsthatcanbepartofatestcaseexecution.
CitrusReferenceGuide
34Testcase
![Page 35: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/35.jpg)
Theactionsarecombinedinfreesequencetoeachothersothatthetesterisabletodeclareaspecialactionchaininsidethetest.Theseactionscanbesendingorreceivingmessages,delayingthetest,validatingthedatabaseandsoon.Step-by-stepthetestproceedsthroughtheactionchain.Incaseonesingleactionfailsbyreasonthewholetestcaseisredanddeclarednotsuccessful.
Finallytestsection
Javadevelopersmightbefamiliarwiththeconceptofdoingsomethinginthefinallycodesection.Thefinallysectioncontainsalistoftestactionsthatwillbeexecutedguaranteedattheveryendofthetestcaseeveniferrorsdidoccurduringtheexecutionbefore.Thisistherightplacetotidyupthingsthatwerepreviouslycreatedbythetestlikecleaningupthedatabaseforinstance.Thefinallysectionisdescribedinmoredetailinfinally.Howeverhereisthebasicsyntaxinsideatest.
XMLDSL
<finally><echo><message>Dofinally-regardlessofwhathashappenedbefore</message></echo></finally>
JavaDSLdesigner
@CitrusTestpublicvoidsampleTest()echo("HelloTestFramework");
doFinally(echo("Dofinally-regardlessofanyerrorbefore"));
JavaDSLrunner
@CitrusTestpublicvoidsampleTest()echo("HelloTestFramework");
doFinally().actions(echo("Dofinally-regardlessofanyerrorbefore")
CitrusReferenceGuide
35Testcase
![Page 36: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/36.jpg)
);
Testmetainformation
Theusercanprovidesomeadditionalinformationaboutthetestcase.Themeta-infosectionattheverybeginningofthetestcaseholdsinformationlikeauthor,statusorcreationdate.Indetailthemetainformationisspecifiedlikethis:
XMLDSL
<testcasename="metaInfoTest"><meta-info><author>ChristophDeppisch</author><creationdate>2008-01-11</creationdate><status>FINAL</status><last-updated-by>ChristophDeppisch</last-updated-by><last-updated-on>2008-01-11T10:00:00</last-updated-on></meta-info><description>...</description><actions>...</actions></testcase>
JavaDSLdesignerandrunner
@CitrusTestpublicvoidsampleTest()description("ThisisaTest");author("Christoph");status(Status.FINAL);
echo("HelloCitrus!");
Thestatusallowsfollowingvalues:DRAFT,READY_FOR_REVIEW,DISABLED,FINAL.Themeta-datainformationtoatestisquiteimportanttogivethereaderafirstinformationaboutthetest.Itisalsopossibletogeneratetestdocumentationusingthismeta-datainformation.Thebuilt-inCitrusdocumentationgeneratesHTMLorExceldocumentsthatlistalltestswiththeirmetadatainformationanddescription.
CitrusReferenceGuide
36Testcase
![Page 37: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/37.jpg)
NoteTestswiththestatusDISABLEDwillnotbeexecutedduringatestsuiterun.SosomeonecanjuststartaddingplannedtestcasesthatarenotfinishedyetinstatusDRAFT.Incaseatestisnotrunnableyetbecauseitisnotfinished,someonemaydisableatesttemporarilytoavoidcausingfailuresduringatestrun.UsingthesedifferentstatusesonecaneasilysetuptestplansandreviewtheprogressoftestcoveragebycomparingthenumberofDRAFTteststothoseintheFINALstate.
NowyouknowthepossibilitieshowtowriteCitrustestcasesinXMLorJava.Pleasechoosewhatevercodelanguagetypeyouwant(Java,XML,Springbeansyntax)inordertowriteCitrustestcases.DevelopersmaychooseJava,testerswithoutcodingexperiencemayrunbestwiththeXMLsyntax.WeareconstantlyworkingonevenmoretestwritinglanguagesupportsuchasGroovy,Scala,Xtext,andsoon.IngeneralyoucanmixthedifferentlanguagetypesjustasyoulikewithinyourCitrusprojectwhichgivesyouthebestofflexibility.
CitrusReferenceGuide
37Testcase
![Page 38: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/38.jpg)
TestvariablesTheusageoftestvariablesisacoreconceptwhenwritinggoodmaintainabletests.Thekeyidentifiersofatestcaseshouldbeexposedastestvariablesattheverybeginningofatest.Thiswayhardcodedidentifiersandmultipleredundantvaluesinsidethetestcanbeavoidedfromscratch.Asatesteryoudefinealltestvariablesattheverybeginningofyourtest.
XMLDSL
<variables><variablename="text"value="HelloTestFramework"/><variablename="customerId"value="123456789"/></variables>
JavaDSLdesignerandrunner
variable("text","HelloTestFramework");variable("customerId","123456789");
Theconceptoftestvariablesisessentialwhenwritingcomplextestswithlotsofidentifiersandsemanticdata.Testvariablesarevalidforthewholetestcase.Youcanreferencethemseveraltimesusingacommonvariableexpression"$variable-name".Itisgoodpracticetoprovideallimportantentitiesastestvariables.Thismakesthetesteasiertomaintainandmoreflexible.Allessentialentitiesandidentifiersarepresentrightatthebeginningofthetest,whichmayalsogivetheopportunitytoeasilycreatetestvariantsbysimplychangingthevariablevaluesforothertestscenarios.
Thenameofthevariableisarbitrary.Feelfreetospecifyanynameyoucanthinkof.OfcourseyouneedtobecarefulwithspecialcharactersandreservedXMLentitieslike'&','<','>'.IfyouarefamiliarwithJavaoranyotherprogramminglanguagesimplythinkofthenamingrulesthereandyouwillbefinewithworkingonCitrusvariables,too.Thevalueofavariablecanbeanycharactersequence.ButagainbeawareofspecialXMLcharacterslike"<"thatneedtobeescaped("<")whenusedinvariablevalues.
Theadvantageofvariablesisobvious.Oncedeclaredthevariablescanbereferencedmanytimesinthetest.Thismakesitveryeasytovarydifferenttestcasesbyadjustingthevariablesfordifferentmeans(e.g.usedifferenterrorcodesintestcases).
CitrusReferenceGuide
38Testvariables
![Page 39: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/39.jpg)
Globalvariables
Thelastsectiontoldustousevariablesastheyareveryusefulandextendthemaintainabilityoftestcases.Nowthateverytestcasedefineslocalvariablesyoucanalsodefineglobalvariables.Theglobalvariablesarevalidinalltestsbydefault.Thisisagoodopportunitytodeclareconstantvaluesforalltests.AsthesevariablesareglobalweneedtoaddthosetothebasicSpringapplicationcontextfile.ThefollowingexampledemonstrateshowtoaddglobalvariablesinCitrus:
<citrus:global-variables><citrus:variablename="projectName"value="CitrusIntegrationTesting"/><citrus:variablename="userName"value="TestUser"/></citrus:global-variables>
WeaddtheSpringbeancomponenttotheapplicationcontextfile.Thecomponentreceivesalistofname-valuevariableelements.Youcanreferencetheglobalvariablesinyourtestcasesasusual.
Anotherpossibilitytosetglobalvariablesistoloadthosefromexternalpropertyfiles.Thismaygiveyoumorepowerfulglobalvariableswithuserspecificpropertiesforinstance.Seehowtoloadpropertyfilesasglobalvariablesinthisexample:
<citrus:global-variables><citrus:filepath="classpath:global-variable.properties"/></citrus:global-variables>
Wehavejustaddedafilepathreferencetotheglobalvariablescomponent.Citrusloadsthepropertyfilecontentasglobaltestvariables.Youcanmixpropertyfileandname-valuepairvariabledefinitionsintheglobalvariablescomponent.
NoteTheglobalvariablescanhavevariableexpressionsandCitrusfunctions.Itispossibletousepreviouslydefinedglobalvariablesasvaluesofnewvariables,likeinthisexample:
user=Citrusgreeting=Hello$user!date=citrus:currentDate('yyyy-MM-dd')
CreatevariableswithCDATA
CitrusReferenceGuide
39Testvariables
![Page 40: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/40.jpg)
WhenusingthXMLtestcaseDSLwecannothaveXMLvariablevaluesoutofthebox.ThiswouldinterferewiththeXMLDSLelementsdefinedintheCitrustestcaseXSDschema.YoucanuseCDATAsectionswithinthevariablevalueelementinordertodothisthough.
<variables><variablename="persons"><value><data><![CDATA[<persons><person><name>Theodor</name><age>10</age></person><person><name>Alvin</name><age>9</age></person></persons>]]></data></value></variable></variables>
ThatishowyoucanuseXMLvariablevaluesintheXMLDSL.IntheJavaDSLwedonothavetheseproblems.
CreatevariableswithGroovy
Youcanalsouseascripttocreatevariablevalues.Thisisextremelyhandywhenyouhaveverycomplexvariablevalues.JustcodeasmallGroovyscriptforinstanceinordertodefinethevariablevalue.Asmallsampleshouldgiveyoutheideahowthatworks:
<variables><variablename="avg"><value><scripttype="groovy">
</script></value>
CitrusReferenceGuide
40Testvariables
![Page 41: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/41.jpg)
</variable><variablename="sum"><value><scripttype="groovy">
</script></value></variable></variables>
Weusethescriptcoderightinsidethevariablevaluedefinition.Thevalueofthevariableistheresultofthelastoperationperformedwithinthescript.Forlongerscriptcodetheuseof<![CDATA[]]>sectionsisrecommended.
CitrususesthejavaxScriptEnginemechanisminordertoevaluatethescriptcode.BydefaultGroovyissupportedinanyCitrusproject.SoyoucanaddadditionalScriptEngineimplementationstoyourprojectandsupportotherscripttypes,too.
Escapingvariablesexpression
Thetestvariablesexpressionsyntax"$variable-name"ispreservedtoevaluatetoatestvariablewithinthecurrenttestcontext.Howeverthesamesyntaxmaybepartofamessagecontentasis.Soyouneedtosomehowescapethesyntaxfrombeeinginterpretedastestvariablesyntax.Youcandothisbyusingthevariableexpressionescaping//charactersequencewrappingtheactualvariablenamelikethis
Thisisaescapedvariableexpression$//escaped//andshouldnotleadtounknownvariableexceptionswithinCitrus.
Theescapedexpression$//escaped//abovewillresultinthestring$escapedwhereescapedisnottreatedasatestvariablenamebutasanormalstringinthemessagepayload.ThiswayyouareabletohavethesamevariablesyntaxinamessagecontentwithoutinterferingwiththeCitrusvariableexpressionsyntax.AsaresultCitruswillnotcomplainaboutnotfindingthetestvariableescapedinthecurrentcontext.Thevariablesyntaxescapingcharacters//areautomaticallyremovedwhentheexpressionisprocessedbyCitrus.Sowewillgetthefollowingresultafterprocessing.
Thisisaescapedvariableexpression$escapedandshouldnotleadtounknownvariableexceptionswithinCitrus.
CitrusReferenceGuide
41Testvariables
![Page 42: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/42.jpg)
CitrusReferenceGuide
42Testvariables
![Page 43: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/43.jpg)
RunningtestsCitrustestcasesarenothingbutJavaclassesthatgetexecutedwithinaJavaruntimeenvironment.EachCitrustestthereforerelatestoaJavaclassrepresentingaJUnitorTestNGunittest.AsoptionaladdonaCitrustestcanhaveaXMLtestdeclarationfile.ThisisforthoseofyouthatdonotwanttocodeinJava.InthiscasetheXMLpartholdsallactionstotellCitruswhatshouldhappeninthetestcase.TheJavapartwillthenjustberesponsiblefortestexecutionandisnotlikelytobechangedatall.InthefollowingsectionsweconcentrateontheJavapartandthetestexecutionmechanism.
IfyoucreatenewtestcasesinCitrus-forinstanceviaMavenpluginorANTbuildscript-Citrusgeneratesbothpartsinyourtestdirectory.Forexample:ifyoucreateanewtestnamedMyFirstCitrusTestyouwillfindthesetwofilesasaresult:
src/it/tests/com/consol/citrus/MyFirstCitrusTest.xmlsrc/it/java/com/consol/citrus/MyFirstCitrusTest.java
NoteIfyouprefertojustwriteJavacodeyoucanthrowawaytheXMLpartimmediatelyandcontinueworkingwiththeJavapartonly.IncaseyouarefamiliarwithwritingJavacodeyoumayjustskipthetesttemplategenerationviaMavenorANTandpreferablyjustcreatenewCitrusJavatestclassesonyourown.
Withthecreationofthistestwehavealreadymadeaveryimportantdecision.Duringcreation,Citrusasksyouwhichexecutionframeworkshouldbeusedforthistest.Therearebasicallythreeoptionsavailable:testngandjunit.
SowhyisCitrusrelatedtoUnittestsalthoughitisintendedtobeaframeworkforintegrationtesting?Theanswertothisquestionisquitesimple:ThisisbecauseCitruswantstobenefitfrombothJUnitandTestNGforJavatestexecution.BoththeJUnitandTestNGJavaAPIsoffervariouswaysofexecutionandbothframeworksarewidelysupportedbyothertools(e.g.continuousbuild,buildlifecycle,developmentIDE).
Usersmightalreadyknowoneoftheseframeworksandthechancesaregoodthattheyarefamiliarwithatleastoneofthem.EverythingyoucandowithJUnitandTestNGtestcasesyoucandowithCitrustestsalso.IncludethemintoyourMavenbuildlifecycle.ExecutetestsfromyourIDE(Eclipse,IDEAorNetBeans).Includethemintoa
CitrusReferenceGuide
43Run
![Page 44: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/44.jpg)
continuousbuildtool(e.g.Jenkins).GeneratetestexecutionreportsandtestcoveragereportswithSonar,Coberturaandsoon.ThepossibilitieswithJUnitandTestNGareamazing.
SoletushaveacloserlookattheCitrusTestNGandJUnitintegration.
RunwithTestNG
TestNGstandsfornextgenerationtestingandhashadagreatinfluenceinaddingJavaannotationstotheunittestcommunity.CitrusisabletogenerateTestNGJavaclassesthatareexecutableastestcases.SeethefollowingstandardtemplatethatCitruswillgeneratewhenhavingnewtestcases:
packagecom.consol.citrus.samples;
importorg.testng.annotations.Test;importcom.consol.citrus.annotations.CitrusXmlTest;importcom.consol.citrus.testng.AbstractTestNGCitrusTest;
/***TODO:Description**@authorUnknown*/@TestpublicclassSampleITextendsAbstractTestNGCitrusTest@CitrusXmlTest(name="SampleIT")publicvoidsampleTest()
IfyouarefamiliarwithTestNGyouwillseethatthegeneratedJavaclassisnothingbutanormalTestNGtestclass.WejustextendabasicCitrusTestNGclasswhichenablestheCitrustestexecutionfeaturesforus.BesidesthatwehaveausualTestNG@Testannotationplacedonourclasssoallmethodsinsidetheclasswillbeexecutedasseparatetestcase.
ThegoodnewsisthatwecanstillusethefantasticTestNGfeaturesinourtestclass.Youcanthinkofparalleltestexecution,testgroups,setupandteardownoperationsandsoon.Justtogiveanexamplewecansimplyaddatestgrouptoourtestlikethis:
@Test(groups="long-running")
FormoreinformationonTestNGpleasevisittheofficialhomepage,whereyoufindacompletereferencedocumentation.
CitrusReferenceGuide
44Run
![Page 45: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/45.jpg)
YoumighthavenoticedthattheexampleaboveloadstestcasesfromXML.Thisiswhyweareusingthe@CitrusXmlTestannotation.AgainthisapproachisforpeoplethatwanttowritenoJavacode.ThetestlogicisthenprovidedintheXMLtestdefinition.WediscussXMLtestsinCitrusinmoredetailinrun-xml-tests.NextletshavealookataTestNGJavaDSLtest.
WhenwritingtestsinpureJavawehaveprettymuchtheexactsamelogicthatappliestoexecutingCitrustestcases.TheCitrustestextendsfromaTestNGbaseclassandusesthenormal@Testannotationsonmethodorclasslevel.HereisashortsampleTestNGJavaclassforthis:
importorg.testng.annotations.Test;importcom.consol.citrus.annotations.CitrusTest;importcom.consol.citrus.dsl.testng.TestNGCitrusTestDesigner;
@TestpublicclassMyFirstTestDesignerextendsTestNGCitrusTestDesigner@CitrusTest(name="MyFirstIT")publicvoidmyFirstTest()description("Firstexampleshowingthebasictestcasedefinitionelements!");
variable("text","HelloTestFramework");
echo("$test");
YouseetheclassisquitesimilartotheXMLtestvariation.NowweextendaCitrustestdesignerclasswhichenablestheJavaDSLfeaturesinadditiontotheTestNGtestexecutionforus.Thebasic@TestannotationforTestNGhasnotchanged.WestillhaveausualTestNGclasswiththepossibilityofseveralmethodseachrepresentingaseparateunittest.
Nowwhathaschangedisthe@CitrusTestannotation.NowtheCitrustestlogicisplaceddirectlyasthemethodbodywithusingtheJavadomainspecificlanguagefeatures.TheXMLCitrustestpartisnotnecessaryanymore.IfyouarewonderingaboutthedesignersuperclassandtheJavaDSLmethodsforaddingthetestlogictoyourtestpleasebepatientwewilllearnmoreabouttheJavaDSLfeaturesinthisreferenceguidelateron.
UptonowwejustconcentrateontheTestNGintegrationthatisquiteeasyisn'tit.
UsingTestNGDataProviders
CitrusReferenceGuide
45Run
![Page 46: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/46.jpg)
TestNGasaframeworkcomeswithlotsofgreatfeaturessuchasdataproviders.Dataprovidersexecuteatestcaseseveraltimes.Eachtestexecutiongetsaspecificparametervalue.WithCitrusyoucanusethosedataproviderparametersinsidethetestasvariables.SeethenextlistingonhowtouseTestNGdataprovidersinCitrus:
publicclassDataProviderITextendsAbstractTestNGCitrusTest
@CitrusXmlTest@CitrusParameters("message")@Test(dataProvider="messageDataProvider")publicvoidDataProviderIT(ITestContexttestContext)
@DataProviderpublicObject[][]messageDataProvider()returnnewObject[][]"HelloWorld!","HalloWelt!","HiCitrus!",;
AbovetestcasemethodisannotatedwithTestNGdataprovidercalledmessageDataProvider.Inthesameclassyoucanwritethedataproviderthatreturnsalistofparametervalues.TestNGwillexecutethetestcaseseveraltimesaccordingtotheprovidedparameterlist.Eachexecutionisshippedwiththerespectiveparametervalue.Accordingtothe@CitrusParameterannotationthetestwillhaveatestvariablecalledmessagethatisaccessibleasusual.
RunwithJUnit
JUnitisaverypopularunittestframeworkforJavaapplicationswidelyacceptedandwidelysupportedbymanytools.IngeneralCitrussupportsbothJUnitandTestNGastestexecutionframeworks.AlthoughtheTestNGcustomizationfeaturesareslightlymorepowerfulthanthoseofferedbyJUnityouasaCitrususershouldbeabletousetheframeworkofyourchoice.Thecompletesupportforexecutingtestcaseswithpackagescansandmultipleannotatedmethodsisgivenforbothframeworks.IfyouchoosejunitasexecutionframeworkCitrusgeneratesaJavafilethatlookslikethis:
packagecom.consol.citrus.samples;
importorg.junit.Test;
CitrusReferenceGuide
46Run
![Page 47: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/47.jpg)
importcom.consol.citrus.annotations.CitrusXmlTest;importcom.consol.citrus.junit.AbstractJUnit4CitrusTest;
/***TODO:Description**@authorUnknown*/publicclassSampleITextendsAbstractJUnit4CitrusTest@Test@CitrusXmlTest(name="SampleIT")publicvoidsampleTest()
JUnitandTestNGasframeworksrevealslightdifferences,buttheideaisthesame.WeextendabaseJUnitCitrustestclassandhaveonetomanytestmethodsthatloadtheXMLCitrustestcasesforexecution.AsyoucanseethetestclasscanholdseveralannotatedtestmethodsthatgetexecutedasJUnittests.ThefinethinghereisthatwearestillabletouseallJUnitfeaturessuchasbefore/aftertestactionsorenable/disabletests.
TheJavaJUnitclassesaresimplyresponsibleforloadingandexecutingtheCitrustestcases.CitrustakescareonloadingtheXMLtestasafilesystemresourceandtosetuptheSpringapplicationcontext.Thetestisexecutedandsuccess/failurestateisreportedexactlylikeausualJUnitunittestwoulddo.ThisalsomeansthatyoucanexecutethisCitrusJUnitclasslikeeveryotherJUnittest,especiallyoutofanyJavaIDE,withMaven,withANTandsoon.ThismeansthatyoucaneasilyincludetheCitrustestexecutionintoyousoftwarebuildinglifecycleandcontinuousbuild.
TipSonowweknowbothTestNGandJUnitsupportinCitrus.Whichframeworkshouldsomeonechoose?Tobehonest,thereisnoeasyanswertothisquestion.Thebasicfeaturesareequivalent,butTestNGoffersbetterpossibilitiesfordesigningmorecomplextestsetupwithtestgroupsandtasksbeforeandafteragroupoftests.ThisiswhyTestNGisthedefaultoptioninCitrus.Butintheendyouhavetodecideonyourownwhichframeworkfitsbestforyourproject.
Thefirstexampleseenhereisusing@CitrusXmlTestannotationinordertoloadaXMLfileastest.TheJavapartisthenjustanemptyenvelopeforexecutingthetestwithJUnit.ThisapproachisforthoseofyouthatarenotfamiliarwithJavaatall.YoucanfindmoreinformationonloadingXMLfilesasCitrustestsinrun-xml-tests.SecondlyofcoursewealsohavethepossibilitytousetheCitrusJavaDSLwithJUnit.Seethefollowingexampleonhowthislookslike:
CitrusReferenceGuide
47Run
![Page 48: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/48.jpg)
packagecom.consol.citrus.samples;
importcom.consol.citrus.annotations.CitrusTest;importcom.consol.citrus.dsl.JUnit4CitrusTestDesigner;importorg.junit.Test;
/***TODO:Description**@authorUnknown*/publicclassSampleITextendsJUnit4CitrusTestDesigner
@Test@CitrusTestpublicvoidEchoSampleIT()variable("time","citrus:currentDate()");echo("HelloCitrus!");echo("CurrentTimeis:$time");
@Test@CitrusTest(name="EchoIT")publicvoidechoTest()echo("HelloCitrus!");
TheJavaDSLtestcaselooksquitefamiliaraswealsousetheJUnit4@Testannotationinordertomarkourtestforunittestexecution.Inadditiontothatweadda@CitrusTestannotationandextendfromabasicJUnit4CitrustestdesignerwhichenablestheJavadomainspecificlanguagefeatures.TheCitrustestlogicgoesdirectlytothemethodblock.ThereisnoneedforaXMLtestfileanymore.
Asyoucanseethe@CitrusTestannotationsupportsmultipletestmethodsinonesingleclass.EachtestispreparedandexecutedseparatelyjustasyouknowitfromJUnit.YoucandefineanexplicitCitrustestnamethatisusedinCitrustestreports.Ifnoexplicittestnameisgiventhetestmethodnamewillbeusedasatestname.
IfyouneedtoknowmoredetailsaboutthetestdesignerandonhowtousetheCitrusJavaDSLjustcontinuewiththisreferenceguide.Wewilldescribethecapabilitiesindetaillateron.
RunningXMLtests
CitrusReferenceGuide
48Run
![Page 49: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/49.jpg)
Nowwealsousethe@CitrusXmlTestannotationintheJavaclass.ThisannotationmakesCitrussearchforaXMLfilethatrepresentstheCitrustestwithinyourclasspath.LateronwewillalsodiscussanotherCitrusannotation(@CitrusTest)whichstandsfordefiningtheCitrustestjustwithJavadomainspecificlanguagefeatures.FornowwecontinuetodealwiththeXMLCitrustestexecution.
ThedefaultnamingconventionrequiresaXMLfilewiththetestsnameinthesamepackagethattheJavaclassisplacedin.InthebasicexampleabovethismeansthatCitrussearchesforaXMLtestfileincom/consol/citrus/samples/SampleIT.xml.YoutellCitrustosearchforanotherXMLfilebyusingthe@CitrusXmlTestannotationproperties.Followingannotationpropertiesarevalid:
name:Listoftestcasenamestoexecute.NamesalsodefineXMLfilenamestolookfor(.xmlfileextensionisnotneededhere).packageName:CustompackagelocationfortheXMLfilestoloadpackageScan:ListofpackagesthatareautomaticallyscannedforXMLtestfilestoexecute.ForeachXMLfilefoundseparatetestisexecuted.NotethatthisperformsaJavaClasspathpackagescansoallXMLfilesinpackageareassumedtobevalidCitrusXMLtestcases.InordertominimizetheamountofaccidentallyloadedXMLfilesthescanwillonlyloadXMLfileswith*/Test.xmland*/IT.xmlfilenamepattern.
YoucanalsomixthevariousCitrusXmlTestannotationpatternsinasingleJavaclass.SoweareabletohaveseveraltestcasesinonesingleJavaclass.EachannotatedmethodrepresentsoneormoreCitrusXMLtestcases.Sethefollowingexampletoseewhatthisisabout.
@TestpublicclassSampleITextendsAbstractTestNGCitrusTest@CitrusXmlTest(name="SampleIT")publicvoidsampleTest()
@CitrusXmlTest(name="SampleIT","AnotherIT")publicvoidmultipleTests()
@CitrusXmlTest(name="OtherIT",packageName="com.other.testpackage")publicvoidotherPackageTest()
@CitrusXmlTest(packageScan="com.some.testpackage","com.other.testpackage")publicvoidpackageScanTest()
CitrusReferenceGuide
49Run
![Page 50: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/50.jpg)
Youarefreetocombinethesetestannotationsasyoulikeinyourclass.AsthewholeJavaclassisannotatedwiththeTestNG@Testannotationeachmethodgetsexecutedautomatically.CitruswillalsotakecareonexecutingeachXMLtestcaseasaseparateunittest.SothetestreportswillhavetheexactnumberofexecutedtestsandtheJUnit/TestNGtestreportsdohavetheexacttestoutlineforfurtherusage(e.g.incontinuousbuildreports).
NoteWhentestexecutiontakesplaceeachtestmethodannotationisevaluatedinsequence.XMLtestcasesthatmatchseveraltimes,forinstancebyexplicitnamereferenceandapackagescanwillbeexecutedseveraltimesrespectively.
Thebestthingaboutusingthe@CitrusXmlTestannotationisthatyoucancontinuetousethefabulousTestNGcapabilities(e.g.testgroups,invocationcount,threadpools,dataproviders,andsoon).
SonowwehaveseenhowtoexecuteaCitrusXMLtestwithTestNG.
CitrusReferenceGuide
50Run
![Page 51: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/51.jpg)
ConfigurationYouhaveseveraloptionsincustomizingtheCitrusprojectconfiguration.Citrususesdefaultsettingsthatcanbeoverwrittentosomeextend.AsaframeworkCitrusinternallyworkswiththeSpringIoCcontainer.SoCitruswillstartaSpringapplicationcontextandregisterseveralcomponentsasSpringbeans.Youcancustomizethebehaviorofthesebeansandyoucanaddcustomsettingsbysettingsystemproperties.
CitrusSpringXMLapplicationcontext
CitrusstartsaSpringapplicationcontextandaddssomedefaultSpringbeancomponents.BydefaultCitruswillloadsomeinternalSpringJavaconfigclassesdefiningthosebeancomponents.Atsomepointyoumightaddsomecustombeanstothatbasicapplicationcontext.ThisiswhyCitruswillsearchforcustomSpringapplicationcontextfilesinyourproject.Theseareautomaticallyloaded.
BydefaultCitruslooksforcustomXMLSpringapplicationcontextfilesinthislocation:classpath*:citrus-context.xml.Soyoucanaddafilenamedcitrus-context.xmltoyourprojectclasspathandCitruswillloadallSpringbeansautomatically.
ThelocationofthisfilecanbecustomizedbysettingaSystempropertycitrus.spring.application.context.SoyoucancustomizetheXMLSpringapplicationcontextfilelocation.TheSystempropertyissettablewithMavensurefireandfailsafepluginforinstanceorviaJavabeforetheCitrusframeworkgetsloaded.
SeethefollowingsampleXMLconfigurationwhichisanormalSpringbeanXMLconfiguration:
<?xmlversion="1.0"encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:citrus="http://www.citrusframework.org/schema/config"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.citrusframework.org/schema/confighttp://www.citrusframework.org/schema/config/citrus-config.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"
<citrus:schema-repositoryid="schemaRepository"/>
</beans>
CitrusReferenceGuide
51Configuration
![Page 52: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/52.jpg)
NowyoucanaddsomeSpringbeansandyoucanusetheCitrusXMLcomponentssuchasschema-repositoryforaddingcustombeansandcomponentstoyourCitrusproject.CitrusprovidesseveralnamespacesforcustomSpringXMLcomponents.Thesearedescribedinmoredetailintherespectivechaptersandsectionsinthisreferenceguide.
TipYoucanalsouseimportstatementsinthisSpringapplicationcontextinordertoloadotherconfigurationfiles.SoyouarefreetomodularizeyourconfigurationinseveralfilesthatgetloadedbyCitrus.
CitrusSpringJavaconfig
UsingXMLSpringapplicationcontextconfigurationisthedefaultbehaviorofCitrus.HoweversomepeoplemightpreferpureJavacodeconfiguration.YoucandothatbyaddingaSystempropertycitrus.spring.java.configwithacustomSpringJavaconfigclassasvalue.
System.setProperty("citrus.spring.java.config",MyCustomConfig.class.getName())
CitruswillloadtheSpringbeanconfigurationsinMyCustomConfig.classasJavaconfigthen.SeethefollowingexampleforcustomSpringJavaconfiguration:
importcom.consol.citrus.TestCase;importcom.consol.citrus.report.*;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;
@ConfigurationpublicclassMyCustomConfig
@Bean(name="customTestListener")publicTestListenercustomTestListener()returnnewPlusMinusTestReporter();
privatestaticclassPlusMinusTestReporterextendsAbstractTestListenerimplementsTestReporter
/**Logger*/privateLoggerlog=LoggerFactory.getLogger(CustomBeanConfig.class);
privateStringBuildertestReport=newStringBuilder();
@OverridepublicvoidonTestSuccess(TestCasetest)
CitrusReferenceGuide
52Configuration
![Page 53: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/53.jpg)
testReport.append("+");
@OverridepublicvoidonTestFailure(TestCasetest,Throwablecause)testReport.append("-");
@OverridepublicvoidgenerateTestResults()log.info(testReport.toString());
@OverridepublicvoidclearTestResults()testReport=newStringBuilder();
YoucanalsomixXMLandJavaconfigurationsoCitruswillloadbothconfigurationtotheSpringbeanapplicationcontextonstartup.
Citrusapplicationproperties
TheCitrusframeworkreferencessomebasicSystempropertiesthatcanbeoverwritten.ThepropertiesareloadedfromJavaSystemandarealsosettableviapropertyfile.Justaddapropertyfilenamedcitrus-application.propertiestoyourprojectclasspath.Thispropertyfilecontainscustomizedsettingssuchas:
citrus.spring.application.context=classpath*:citrus-custom-context.xmlcitrus.spring.java.config=com.consol.citrus.config.MyCustomConfigcitrus.file.encoding=UTF-8citrus.default.message.type=XMLcitrus.xml.file.name.pattern=/**/*Test.xml,/**/*IT.xml
Citrusloadstheseapplicationpropertiesatstartup.AllpropertiesarealsosettablewithJavaSystemproperties.Thelocationofthecitrus-application.propertiesiscustomizablewiththeSystempropertycitrus.application.config.
System.setProperty("citrus.application.config","custom/path/to/citrus-application.properties"
CitrusReferenceGuide
53Configuration
![Page 54: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/54.jpg)
Atthemomentyoucanusethesepropertiesforcustomization:
citrus.spring.application.context:FilelocationforSpringXMLconfigurationscitrus.spring.java.config:ClassnameforSpringJavaconfigcitrus.file.encoding:DefaultfileencodingusedinCitruswhenreadingandwritingfilecontentcitrus.default.message.type:Defaultmessagetypeforvalidatingpayloadscitrus.xml.file.name.pattern:FilenamepatternsusedforXMLtestfilepackagescan
CitrusReferenceGuide
54Configuration
![Page 55: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/55.jpg)
EndpointsInoneofthepreviouschapterswehavediscussedthebasictestcasestructureasweintroducedvariablesandtestactions.Thesectioncontainsalistoftestactionsthattakeplaceduringthetestcase.Eachtestactionisexecutedinsequentialorderbydefault.Citrusoffersseveralbuilt-intestactionsthattheusercanchoosefromtoconstructacomplextestingworkflowwithouthavingtocodeeverythingfromscratch.InparticularCitrusaimstoprovideallthetestactionsthatyouneedaspredefinedcomponentsreadyforyoutouse.Thegoalistominimizethecodingeffortforyousoyoucanconcentrateonthetestlogicitself.
ExactlythesameapproachisusedinCitrustoprovideready-to-useendpointcomponentforconnectingtodifferentmessagetransports.Thereareseveralwaysinanenterpriseapplicationtoexchangemessageswithsomeotherapplication.WehavesynchronousinterfaceslikeHttpandSOAPWebServices.WehaveasynchronousmessagingwithJMSorfiletransferFTPinterfaces.
Citrusprovidesendpointcomponentsasclientandservertoconnectwiththesetypicalmessagetransports.SoyouasatestermustnotcareabouthowtosendamessagetoaJMSqueue.TheCitrusendpointsareconfiguredintheSpringapplicationcontextandreceiveendpointspecificpropertieslikeendpointuriorportsormessagetimeoutsasconfiguration.
ThenextfigureshowsatypicalmessagesendingendpointcomponentinCitrus:
Theendpointproducerpublishesmessagestoadestination.ThisdestinationcanbeaJMSqueue/topic,aSOAPWebServiceendpoint,aHttpURL,aFTPfolderdestinationandsoon.Theproducerjusttakesapreviouslydefinedmessagedefinition(headerandpayload)andsendsittothemessagedestination.
SimilartothatCitrusdefinestheseveralendpointconsumercomponentstoconsumemessagesfromdestinations.ThiscanbeasimplesubscriptiononmessagechannelsandJMSqueues/topics.IncaseofSOAPWebServicesandHttpGET/POSTthingsare
CitrusReferenceGuide
55Endpoints
![Page 56: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/56.jpg)
morecomplicatedaswehavetoprovideaservercomponentthatclientscanconnectto.Wewillhandleserverrelatedcommunicationinmoredetaillateron.Fornowtheendpointconsumercomponentinitsmostsimplewayisdefinedlikethis:
ThisisallyouneedtoknowaboutCitrusendpoints.WehavementionedthattheendpointsaredefinedintheSpringapplicationcontext.Let'shaveasimpleexamplethatshowsthebasicidea:
<citrus-jms:endpointid="helloServiceEndpoint"destination-name="Citrus.HelloService.Request.Queue"connection-factory="myConnectionFacotry"/>
ThisisasimpleJMSendpointcomponentinCitrus.TheendpointXMLbeandefinitionfollowsacustomXMLnamespaceanddefinesendpointspecificpropertiesliketheJMSdestinationnameandtheJMSconnectionfactory.Theendpointidisasignificantpropertyasthetestcaseswillreferencethisendpointwhensendingandreceivingmessagesbyitsidentifier.
Inthenextsectionsyouwilllearnhowatestcaseusesthoseendpointcomponentsforproducingandconsumingmessages.
Sendmessageswithendpoints
Theactioninatestcasepublishesmessagestoadestination.Theactualmessagetransportconnectionisdefinedwiththeendpointcomponent.Thetestcasesimplydefinesthemessagecontentsandreferencesapredefinedmessageendpointcomponentbyitsidentifier.EndpointspecificconfigurationsarecentralizedintheSpringbeanapplicationcontextwhilemultipletestcasescanreferencetheendpointtoactuallypublishtheconstructedmessagetoadestination.ThereareseveralmessageendpointimplementationsinCitrusavailablerepresentingdifferenttransportprotocolslikeJMS,SOAP,HTTP,TCP/IPandmanymore.
Againthetypeoftransporttouseisnotspecifiedinsidethetestcasebutinthemessageendpointdefinition.Theseparationofconcerns(testcase/messagesendertransport)givesusagoodflexibilityofourtestcases.Thetestcasedoesnotknowanythingaboutconnectionfactories,queuenamesorendpointuri,connectiontimeoutsandsoon.The
CitrusReferenceGuide
56Endpoints
![Page 57: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/57.jpg)
transportinternalsunderneathasendingtestactioncanchangeeasilywithoutaffectingthetestcasedefinition.WewillseelaterinthisdocumenthowtocreatedifferentmessageendpointsforvarioustransportsinCitrus.Fornowweconcentrateonconstructingthemessagecontenttobesent.
Weassumethatthemessage'spayloadwillbeplainXMLformat.CitrususesXMLasthedefaultdataformatformessagepayloaddata.ButCitrusisnotlimitedtoXMLmessageformatthough;youcanalwaysdefineothermessagedataformatssuchasJSON,plaintext,CSV.AsXMLisstillaverypopularmessageformatinenterpriseapplicationsandmessage-basedsolutionarchitectureswehavethisasadefaultformat.AnywayCitrusworksbestonXMLpayloadsandyouwillseealotofexamplecodeinthisdocumentusingXML.Finallyletushavealookatafirstexamplehowasendingactionisdefinedinthetest.
XMLDSL
<testcasename="SendMessageTest"><description>Basicsendmessageexample</description>
<actions><sendendpoint="helloServiceEndpoint"><message><payload><TestMessage><Text>Hello!</Text></TestMessage></payload></message><header><elementname="Operation"value="sayHello"/></header></send></actions></testcase>
Nowletshaveacloserlookatthesendingaction.The'endpoint'attributemightcatchyourattentionfirst.ThisattributereferencesthemessageendpointinCitrusconfigurationbyitsidentifier.Aspreviouslymentionedthemessageendpointdefinitionlivesinaseparateconfigurationfileandcontainstheactualmessagetransportsettings.Inthisexamplethe"helloServiceEndpoint"isreferencedwhichisaJMSendpointforsendingoutmessagestoaJMSqueueforinstance.
CitrusReferenceGuide
57Endpoints
![Page 58: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/58.jpg)
Thetestcaseisnotawareofanytransportdetails,becauseitdoesnothaveto.Theadvantagesareobvious:Ontheonehandmultipletestcasescanreferencethemessageendpointdefinitionforbetterreuse.Secondlytestcasesareindependentofmessagetransportdetails.Soconnectionfactories,usercredentials,endpointurivaluesandsoonarenotpresentinthetestcase.
Inotherwordsthe"endpoint"attributeofthe<send>elementspecifieswhichmessageendpointdefinitiontouseandthereforewherethemessageshouldgoto.OnceagainallavailablemessageendpointsareconfiguredinaseparateCitrusconfigurationfile.Besuretoalwayspicktherightmessageendpointtypeinordertopublishyourmessagetotherightdestination.
IfyoudonotliketheXMLlanguageyoucanalsousepureJavacodetodefinethesametest.InJavayouwouldalsomakeuseofthemessageendpointdefinitionandreferencethisinstance.ThesametestasshownaboveinJavaDSLlookslikethis:
JavaDSLdesigner
importorg.testng.ITestContext;importorg.testng.annotations.Test;importcom.consol.citrus.annotations.CitrusTest;importcom.consol.citrus.dsl.testng.TestNGCitrusTestDesigner;
@TestpublicclassSendMessageTestDesignerextendsTestNGCitrusTestDesigner
@CitrusTest(name="SendMessageTest")publicvoidsendMessageTest()description("Basicsendmessageexample");
send("helloServiceEndpoint").payload("<TestMessage>"+"<Text>Hello!</Text>"+"</TestMessage>").header("Operation","sayHello");
InsteadofusingtheXMLtagsforsendweusemethodsfromTestNGCitrusTestDesignerclass.Thesamemessageendpointisreferencedwithinthesendmessageaction.ThepayloadisconstructedasplainJavacharactersequencewhichisabitverbose.Wewillseelateronhowwecanimprovethis.Fornowitisimportanttounderstandthecombinationofsendtestactionandamessageendpoint.
CitrusReferenceGuide
58Endpoints
![Page 59: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/59.jpg)
TipItisgoodpracticetofollownamingconventionswhendefiningnamesformessageendpoints.Theintendedpurposeofthemessageendpointaswellasthesending/receivingactorshouldbeclearwhenchoosingthename.ForinstancemessageEndpoint1,messageEndpoint2willnotgiveyoumuchhintstothepurposeofthemessageendpoint.
ThisisbasicallyhowtosendmessagesinCitrus.Thetestcaseisresponsibleforconstructingthemessagecontentwhilethepredefinedmessageendpointholdstransportspecificsettings.Testcasesreferenceendpointcomponentstopublishmessagestotheoutsideworld.Thisisjustthestartofaction.Citrussupportsawholepackageofotherwayshowtodefineandmanipulatethemessagecontents.Readmoreaboutmessagesendingactionsinactions-send.
Receivemessageswithendpoints
Nowwehavealookatthemessagereceivingpartinsidethetest.Asimpleexampleshowshowitworks.
XMLDSL
<receiveendpoint="helloServiceEndpoint"><message><payload><TestMessage><Text>Hello!</Text></TestMessage></payload></message><header><elementname="Operation"value="sayHello"/></header></receive>
Ifwerecapthesendactionofthepreviouschapterwecanidentifysomecommonmechanismsthatapplyforbothsendingandreceivingactions.Thetestactionalsousestheendpointattributeforreferencingapredefinedmessageendpoint.Thistimewewanttoreceiveamessagefromtheendpoint.AgainthetestisnotawareofthetransportdetailssuchasJMSconnections,endpointuri,andsoon.Themessageendpointcomponentencapsulatesthisinformation.
CitrusReferenceGuide
59Endpoints
![Page 60: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/60.jpg)
BeforewegointodetailonvalidatingthereceivedmessagewehaveaquicklookattheJavaDSLvariationforthereceiveaction.ThesamereceiveactionasabovelookslikethisinJavaDSL.
JavaDSLdesigner
@CitrusTestpublicvoidmessagingTest()receive("helloServiceEndpoint").payload("<TestMessage>"+"<Text>Hello!</Text>"+"</TestMessage>").header("Operation","sayHello");
Thereceiveactionwaitsforamessagetoarrive.Thewholetestexecutionisstoppedwhilewaitingforthemessage.Thisisimportanttoensurethestepbysteptestworkflowprocessing.Ofcourseyoucanspecifymessagetimeoutssothereceiverwillonlywaitagivenamountoftimebeforeraisingatimeouterror.Followingfromthattimeoutexceptionthetestcasefailsasthemessagedidnotarriveintime.Citrusdefinesdefaulttimeoutsettingsforallmessagereceivingtasks.
AtthispointyouknowthetwomostimportanttestactionsinCitrus.Sendingandreceivingactionswillbecomethemaincomponentsofyourintegrationtestswhendealingwithlooselycoupledmessagebasedcomponentsinaenterpriseapplicationenvironment.Itisveryeasytocreatecomplexmessageflows,meaningasequenceofsendingandreceivingactionsinyourtestcase.Youcanreplicateusecasesandtestyourmessageexchangewithextendedmessagevalidationcapabilities.Seeactions-receiveforamoredetaileddescriptiononhowtovalidateincomingmessagesandhowtoexpectmessagecontentsinatestcase.
Localmessagestore
Allmessagesthataresentandreceivedduringatestcasearestoredinalocalmemorystorage.Thisisbecausewemightwanttoaccessthemessagecontentlateroninatestcase.Wecandosobyusingmessagestorefunctionsforloadingmessagesthathavebeenexchangedearlierinthetest.WhenstoringamessageinthelocalstorageCitrususesamessagenameasidentifierkey.Thismessagenameislateronusedtoaccessthemessage.Youcandefinethemessagenameinanysendorreceiveaction:
XMLDSL
CitrusReferenceGuide
60Endpoints
![Page 61: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/61.jpg)
<receiveendpoint="helloServiceEndpoint"><messagename="helloMessage"><payload><TestMessage><Text>Hello!</Text></TestMessage></payload></message><header><elementname="Operation"value="sayHello"/></header></receive>
JavaDSLdesigner
@CitrusTestpublicvoidmessagingTest()receive("helloServiceEndpoint").name("helloMessage").payload("<TestMessage>"+"<Text>Hello!</Text>"+"</TestMessage>").header("Operation","sayHello");
ThereceiveoperationabovesetthemessagenametohelloMessage.Themessagereceivedisautomaticallystoredinthelocalstoragewiththatname.Youcanaccessthemessagecontentforinstancebyusingafunction:
<echo><message>citrus:message(helloMessage.payload())</message></echo>
ThefunctionloadsthehelloMessageandprintsthepayloadinformationwiththeechotestaction.IncombinationwithXpathorJsonPathfunctionsthismechanismisagoodwaytoaccesstheexchangedmessagecontentslaterinatestcase.
NoteThestorageisforbothsentandreceivedmessagesinatestcase.Thestorageispertestcaseandcontainsallsentandreceivedmessages.
Whennoexplicitmessagenameisgiventhelocalstoragewillconstructadefaultmessagename.Thedefaultnameisbuiltfromtheaction(sendorreceive)plustheendpointusedtoexchangethemessage.Forinstance:
CitrusReferenceGuide
61Endpoints
![Page 62: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/62.jpg)
send(helloEndpoint)receive(helloEndpoint)
ThenamesabovewouldbegeneratedbyasendandreceiveoperationontheendpointnamedhelloEndpoint.
ImportantThemessagestoreisnotabletohandlemultiplemessageofthesamenameinonetestcase.Somessageswithidenticalnameswilloverwriteexistingmessagesinthelocalstorage.
NowwehaveseenthebasicendpointconceptinCitrus.Theendpointcomponentsrepresenttheconnectionstothetestboundarysystems.Thisishowwecanconnecttothesystemundertestformessageexchange.Andthisisourmaingoalwiththisintegrationtestframework.Wewanttoprovideeasyaccesstocommonmessagetransportsonclientandserversidesothatwecantestthecommunicationinterfacesonarealmessagetransportexchange.
CitrusReferenceGuide
62Endpoints
![Page 63: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/63.jpg)
MessagevalidationWhenCitrusreceivesamessagefromexternalapplicationsitistimetoverifythemessagecontent.Thismessagevalidationincludessyntaxrulesaswellassemanticvaluesthatneedtobecomparedtoanexpectedbehavior.Citrusprovidespowerfulmessagevalidationcapabilities.Eachincomingmessageisvalidatedwithsyntaxandsemantics.Thetesterisabletodefineexpectedmessageheadersandpayloads.Citrusmessagevalidatorimplementationswillcomparethemessagesandreportdifferencesastestfailure.WiththeupcomingsectionswehaveacloserlookatmessagevalidationofXMLmessageswithXPathandXMLschemavalidationandfurthermessageformatslikeJSONandplaintext.
JavaDSLvalidationcallbacks
TheJavaDSLofferssomeadditionalvalidationtricksandpossibilitieswhendealingwithmessagesthataresentandreceivedoverCitrus.Oneofthemisthevalidationcallbackfunctionality.Withthisfeatureyoucanmarshal/unmarshalmessagepayloadsandcodevalidationstepsonJavaobjects.
JavaDSLdesigner
@CitrusTestpublicvoidreceiveMessageTest()receive(bookResponseEndpoint).validationCallback(newMarshallingValidationCallback<AddBookResponseMessage>()@Overridepublicvoidvalidate(AddBookResponseMessageresponse,MessageHeadersheaders)Assert.isTrue(response.isSuccess()););
BydefaultthevalidationcallbackneedssomeXMLunmarshallerimplementationfortransformingtheXMLpayloadtoaJavaobject.CitruswillautomaticallysearchfortheunmarshallerbeaninyourSpringapplicationcontextifnothingspecificisset.Ofcourseyoucanalsosettheunmarshallerinstanceexplicitly.
JavaDSLdesigner
CitrusReferenceGuide
63Validation
![Page 64: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/64.jpg)
@AutowiredprivateUnmarshallerunmarshaller;
@CitrusTestpublicvoidreceiveMessageTest()receive(bookResponseEndpoint).validationCallback(newMarshallingValidationCallback<AddBookResponseMessage>(unmarshaller)@Overridepublicvoidvalidate(AddBookResponseMessageresponse,MessageHeadersheaders)Assert.isTrue(response.isSuccess()););
ObviouslyworkingonJavaobjectsismuchmorecomfortablethanusingtheXMLStringconcatenation.Thisiswhyyoucanalsousethisfeaturewhensendingmessages.
JavaDSLdesigner
@AutowiredprivateMarshallermarshaller;
@CitrusTestpublicvoidsendMessageTest()send(bookRequestEndpoint).payload(createAddBookRequestMessage("978-citrus:randomNumber(10)"),marshaller).header(SoapMessageHeaders.SOAP_ACTION,"addBook");
privateAddBookRequestMessagecreateAddBookRequestMessage(Stringisbn)AddBookRequestMessagerequestMessage=newAddBookRequestMessage();Bookbook=newBook();book.setAuthor("Foo");book.setTitle("FooTitle");book.setIsbn(isbn);book.setYear(2008);book.setRegistrationDate(Calendar.getInstance());requestMessage.setBook(book);returnrequestMessage;
TheexampleabovecreatesaAddBookRequestMessageobjectandputsthisaspayloadtoasendaction.IncombinationwithamarshallerinstanceCitrusisabletocreateaproperXMLmessagepayloadthen.
CitrusReferenceGuide
64Validation
![Page 65: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/65.jpg)
Customizemessagevalidators
IntheprevioussectionswehavealreadyseensomeexamplesonhowtooverwritedefaultmessagevalidatorimplementationsinCitrus.BydefaultallmessagevalidatorscanbeoverwrittenbyplacingaSpringbeanofthesameidtotheSpringapplicationcontext.ThedefaultimplementationsofCitrusare:
defaultXmlMessageValidator:com.consol.citrus.validation.xml.DomXmlMessageValidatordefaultXpathMessageValidator:com.consol.citrus.validation.xml.XpathMessageValidatordefaultJsonMessageValidator:com.consol.citrus.validation.json.JsonTextMessageValidatordefaultJsonPathMessageValidator:com.consol.citrus.validation.json.JsonPathMessageValidatordefaultPlaintextMessageValidator:com.consol.citrus.validation.text.PlainTextMessageValidatordefaultMessageHeaderValidator:com.consol.citrus.validation.DefaultMessageHeaderValidatordefaultBinaryBase64MessageValidator:com.consol.citrus.validation.text.BinaryBase64MessageValidatordefaultGzipBinaryBase64MessageValidator:com.consol.citrus.validation.text.GzipBinaryBase64MessageValidatordefaultXhtmlMessageValidator:com.consol.citrus.validation.xhtml.XhtmlMessageValidatordefaultGroovyXmlMessageValidator:com.consol.citrus.validation.script.GroovyXmlMessageValidatordefaultGroovyTextMessageValidator:com.consol.citrus.validation.script.GroovyScriptMessageValidatordefaultGroovyJsonMessageValidator:com.consol.citrus.validation.script.GroovyJsonMessageValidator
Overwritingasinglemessagevalidatorwithacustomimplementationisthenveryeasy.JustaddyourcustomSpringbeantotheapplicationcontextusingoneofthesedefaultbeanidentifiers.IncaseyouwanttochangethemessagevalidatorgangbyaddingorremovingamessagevalidatorimplementationcompletelyyoucanplaceamessagevalidatorcomponentintheSpringapplicationcontext.
<citrus:message-validators><citrus:validatorref="defaultXmlMessageValidator"/>
CitrusReferenceGuide
65Validation
![Page 66: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/66.jpg)
<citrus:validatorref="defaultXpathMessageValidator"/><citrus:validatorref="defaultGroovyXmlMessageValidator"/><citrus:validatorref="defaultPlaintextMessageValidator"/><citrus:validatorref="defaultMessageHeaderValidator"/><citrus:validatorref="defaultBinaryBase64MessageValidator"/><citrus:validatorref="defaultGzipBinaryBase64MessageValidator"/><citrus:validatorclass="com.consol.citrus.validation.custom.CustomMessageValidator"/><citrus:validatorref="defaultJsonMessageValidator"/><citrus:validatorref="defaultJsonPathMessageValidator"/><citrus:validatorref="defaultGroovyJsonMessageValidator"/><citrus:validatorref="defaultGroovyTextMessageValidator"/><citrus:validatorref="defaultXhtmlMessageValidator"/></citrus:message-validators>
ThelistingaboveaddsacustommessagevalidatorimplementationtothesequenceofmessagevalidatorsinCitrus.Wereferencedefaultmessagevalidatorsandaddaimplementationoftypecom.consol.citrus.validation.custom.CustomMessageValidator.Thecustomimplementationclasshastoimplementthebasicinterfacecom.consol.citrus.validation.MessageValidator.NowCitruswilltrytomatchthecustomimplementationtoincomingmessagetypesandoccasionallyexecutethemessagevalidatorlogic.ThisishowyoucanaddandchangethebasicmessagevalidatorregistryinCitrus.Youcanaddcustomimplementationsfornewmessageformatsveryeasy.
Thesameapproachappliesincaseyouwanttoremoveamessagevalidatorimplementationbybanningitcompletely.Justdeletetheentryinthemessagevalidatorregistrycomponent:
<citrus:message-validators><citrus:validatorref="defaultJsonMessageValidator"/><citrus:validatorref="defaultJsonPathMessageValidator"/><citrus:validatorref="defaultGroovyJsonMessageValidator"/><citrus:validatorref="defaultGroovyTextMessageValidator"/><citrus:validatorref="defaultMessageHeaderValidator"/></citrus:message-validators>
TheCitrusmessagevalidatorcomponentdeletedalldefaultimplementationsexceptofthosedealingwithJSONmessageformat.NowCitrusisonlyabletovalidateJSONmessages.BecarefulasthecompleteCitrusprojectwillbeaffectedbythischange.
CitrusReferenceGuide
66Validation
![Page 67: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/67.jpg)
XMLmessagevalidation
XMLisaverycommonmessageformatespeciallyintheSOAPWebServicesandJMSmessagingworld.CitrusprovidesXMLmessagevalidatorimplementationsthatareabletocompareXMLmessagestructures.ThevalidatorwillnoticedifferencesintheXMLmessagestructureandsupportsXMLnamespaces,attributesandXMLschemavalidation.ThedefaultXMLmessagevalidatorimplementationisactivebydefaultandcanbeoverwrittenwithacustomimplementationusingthebeaniddefaultXmlMessageValidator.
<beanid="defaultXmlMessageValidator"class="com.consol.citrus.validation.xml.DomXmlMessageValidator"
ThedefaultXMLmessagevalidatorisverypowerfulwhenitcomestocompareXMLstructures.Thevalidatorsupportsnamespaceswithdifferentprefixesandattributesalswellasnamespacequalifiedattributes.Seethefollowingsectionsforadetaileddescriptionofallcapabilities.
XMLpayloadvalidation
OnceCitrushasreceivedamessagethetestercanvalidatethemessagecontentsinvariousways.Firstofallthetestercancomparethewholemessagepayloadtoapredefinedcontrolmessagetemplate.
Thereceivingactionoffersfollowingelementsforcontrolmessagetemplates:
<payload>:DefinesthemessagepayloadasnestedXMLmessagetemplate.Thewholemessagepayloadisdefinedinsidethetestcase.
<data>:DefinesaninlineXMLmessagetemplateasnestedCDATA.SlightlydifferenttothepayloadvariationaswedefinethewholemessagepayloadinsidethetestcaseasCDATAsection.
<resource>:DefinesanexpectedXMLmessagetemplateviaexternalfileresources.Thistimethepayloadisloadedatruntimefromtheexternalfile.
Bothwaysinlinepayloaddefinitionorexternalfileresourcegiveusacontrolmessagetemplatethatthetestcaseexpectstoarrive.Citrususesthiscontroltemplateforextendedmessagecomparison.Allelements,namespaces,attributesandnodevalues
CitrusReferenceGuide
67Xml
![Page 68: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/68.jpg)
arevalidatedinthiscomparison.WhenusingXMLmessagepayloadsCitruswillnavigatethroughthewholeXMLstructurevalidatingeachelementanditscontent.SamewithJSONpayloads.
Onlyincasereceivedmessageandcontrolmessageareequaltoeachotherasexpectedthemessagevalidationwillpass.IncasedifferencesoccurCitrusgivesdetailederrormessagesandthetestcasefails.
Thecontrolmessagetemplateisnotnecessarilyverystatic.CitrussupportsvariouswaystoadddynamicmessagecontentontheonesideandontheothersideCitruscanignoresomeelementsthatarenotpartofmessagecomparison(e.g.whengeneratedcontentortimestampsarepartofthemessagecontent).Thetestercanenrichtheexpectedmessagetemplatewithtestvariablesorignoreexpressionssowegetamorerobustvalidationmechanism.Wewilltalkaboutthisinthenextsectionstocome.
WhenusingtheCitrusJavaDSLyouwillfaceaverbosemessagepayloaddefinition.ThisisbecauseJavadoesnotsupportmultilinecharactersequencevaluesasStrings.WehavetouseverboseStringconcatenationwhenconstructingXMLmessagepayloadcontentsforinstance.Inadditiontothatreservedcharacterslikequotesmustbeescapedandlinebreaksmustbeexplicitlyadded.AlltheseimpedimentsletmesuggesttouseexternalfileresourcesinJavaDSLwhendealingwithlargecomplexmessagepayloaddata.Hereisanexample:
JavaDSLdesigner
@CitrusTestpublicvoidreceiveMessageTest()receive("helloServiceServer").payload(newClassPathResource("com/consol/citrus/message/data/TestRequest.xml")).header("Operation","sayHello").header("MessageId","$messageId");
XMLheadervalidation
Nowthatwehavevalidatedthemessagepayloadinvariouswayswearenowinterestedinvalidatingthemessageheader.Thisissimpleasyouhavetodefinetheheadernameandthecontrolvaluethatyouexpect.Justaddthefollowingheadervalidationtoyourreceivingaction.
XMLDSL
CitrusReferenceGuide
68Xml
![Page 69: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/69.jpg)
<header><elementname="Operation"value="GetCustomer"/><elementname="RequestTag"value="$requestTag"/></header>
JavaDSLdesigner
@CitrusTestpublicvoidreceiveMessageTest()receive("helloServiceServer").header("Operation","sayHello").header("MessageId","$messageId");
Messageheadersarerepresentedasname-valuepairs.Eachexpectedheaderelementidentifiedbyitsnamehastobepresentinthereceivedmessage.Inadditiontothattheheadervalueiscomparedtothegivencontrolvalue.IfaheaderentryisnotfoundbyitsnameorthevaluedoesnotfitaccordinglyCitruswillraisevalidationerrorsandthetestcasewillfail.
NoteSometimesmessageheadersmaynotapplytothename-valuepairpattern.ForexampleSOAPheaderscanalsocontainXMLfragments.Citrussupportsthesekindofheaderstoo.PleaseseetheSOAPchapterformoredetails.###IgnoreXMLelements
Someelementsinthemessagepayloadmightnotapplyforvalidationatall.Justthinkofcommunicationtimestampsandynamicvaluesinsideamessage:
Thetimestampvalueinournextexamplewilldynamicallychangefromtestruntotestrunandishardlypredictableforthetester,soletsignoreitinvalidation.
XMLDSL
<message><payload><TestMessage><MessageId>$messageId</MessageId><Timestamp>2001-12-17T09:30:47.0Z</Timestamp><VersionId>@ignore@</VersionId></TestMessage></payload><ignorepath="/TestMessage/Timestamp"/></message>
CitrusReferenceGuide
69Xml
![Page 70: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/70.jpg)
AlthoughwehavegivenastatictimestampvalueinthepayloaddatatheelementisignoredduringvalidationastheignoreXPathexpressionmatchestheelement.Inadditiontothatwealsoignoredtheversionidelementinthisexample.Thistimewithaninline@ignore@expression.ThisisforthoseofyouthatdonotlikeXPath.AsaresulttheignoredmessageelementsareautomaticallyskippedwhenCitruscomparesandvalidatesmessagecontentsanddonotbreakthetestcase.
WhenusingtheJavaDSLthe@ignore@placeholderaswellasXPathexpressionscanbeusedseamlessly.Hereisanexampleofthat:
JavaDSLdesigner
@CitrusTestpublicvoidreceiveMessageTest()receive("helloServiceServer").payload(newClassPathResource("com/consol/citrus/message/data/TestRequest.xml")).header("Operation","sayHello").header("MessageId","$messageId").ignore("/TestMessage/Timestamp");
Ofcourseyoucanusetheinline@ignore@placeholderinanexternalfileresource,too.
CustomizeXMLparserandserializer
WhenworkingwithXMLdataformatparsingandserializingisacommontask.XMLstructuresareparsedtoaDOM(DocumentObjectModel)representationinordertoprocesselements,attributesandtextnodes.AlsoDOMnodeobjectsgetserializedtoaStringmessagepayloadrepresentation.TheXMLparserandserializeriscustomizabletoacertainlevel.BydefaultCitrususestheDOMLevel3LoadandSaveimplementationwithfollowingsettings:
Parsersettings
cdata-sections=truesplit-cdata-sections=falsevalidate-if-schema=trueelement-content-whitespace=false
Serializersettings
format-pretty-print=truesplit-cdata-sections=false
CitrusReferenceGuide
70Xml
![Page 71: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/71.jpg)
element-content-whitespace=true
TheparametersarealsodescribedinW3CDOMconfigurationdocumentation.WecancustomizethedefaultsettingsbyaddingaXmlConfigurerSpringbeantotheCitrusapplicationcontext.
<beanid="xmlConfigurer"class="com.consol.citrus.xml.XmlConfigurer"><propertyname="parseSettings"><map><entrykey="validate-if-schema"value="false"value-type="java.lang.Boolean"/></map></property><propertyname="serializeSettings"><map><entrykey="comments"value="false"value-type="java.lang.Boolean"/><entrykey="format-pretty-print"value="false"value-type="java.lang.Boolean"/></map></property></bean>
NoteThisconfigurationisofglobalnature.AllXMLprocessingoperationswillbeaffectedwiththisconfiguration.
GroovyXMLvalidation
WiththeGroovyXmlSlurperyoucaneasilyvalidateXMLmessagepayloadswithouthavingtodealdirectlywithXML.PeoplewhodonotwanttodealwithXPathmayalsolikethisvalidationalternative.Thetesterdirectlynavigatesthroughthemessageelementsandusessimplecodeassertionsinordertocontrolthemessagecontent.HereisanexamplehowtovalidatemessageswithGroovyscript:
XMLDSL
<receiveendpoint="helloServiceClient"timeout="5000"><message><validate><scripttype="groovy">assertroot.children().size()==4assertroot.MessageId.text()=='$messageId'assertroot.CorrelationId.text()=='$correlationId'assertroot.User.text()=='HelloService'assertroot.Text.text()=='Hello'+context.getVariable("user")</script></validate>
CitrusReferenceGuide
71Xml
![Page 72: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/72.jpg)
</message><header><elementname="Operation"value="sayHello"/><elementname="CorrelationId"value="$correlationId"/></header></receive>
JavaDSLdesigner
@CitrusTestpublicvoidreceiveMessageTest()receive("helloServiceClient").validateScript("assertroot.MessageId.text()=='$messageId';"+"assertroot.CorrelationId.text()=='$correlationId';").header("Operation,"sayHello").header("CorrelationId","$correlationId").timeout(5000L);
TheGroovyXmlSlurpervalidationscriptgoesrightintothemessage-taginsteadofaXMLcontroltemplateorXPathvalidation.TheGroovyscriptsupportsJavaassertstatementsformessageelementvalidation.Citrusautomaticallyinjectstherootelementroottothevalidationscript.ThisistheGroovyXmlSlurperobjectandthestartofelementnavigation.Basedonthisrootelementyoucanaccesschildelementsandattributeswithadotnotatedsyntax.Justusetheelementnamesseparatedbyasimpledot.Veryeasy!Ifyouneedthelistofchildelementsusethechildren()functiononanyelement.Withthetext()functionyougetaccesstotheelement'stext-value.Thesize()isveryusefulforvalidatingthenumberofchildelementswhichcompletesthebasicvalidationstatements.
Asyoucanseefromtheexample,wemayusetestvariableswithinthevalidationscript,too.Citrushasalsoinjectedtheactualtestcontexttothevalidationscript.Thetestcontextobjectholdsalltestvariables.Soyoucanalsoaccessvariableswithcontext.getVariable("user")forinstance.Onthetestcontextyoucanalsosetnewvariablevalueswithcontext.setVariable("user","newUserName").
Thereisevenmoreobjectinjectionforthevalidationscript.WiththeautomaticallyaddedobjectreceivedMessageYouhaveaccesstotheCitrusmessageobjectforthisreceiveaction.Thisenablesyoutodowhateveryouwantwiththemessagepayloadorheader.
XMLDSL
<receiveendpoint="helloServiceClient"timeout="5000">
CitrusReferenceGuide
72Xml
![Page 73: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/73.jpg)
<message><validate><scripttype="groovy">assertreceivedMessage.getPayload(String.class).contains("HelloCitrus!")assertreceivedMessage.getHeader("Operation")=='sayHello'
context.setVariable("request_payload",receivedMessage.getPayload(String.class</script></validate></message></receive>
Thelistingaboveshowssomepowerofthevalidationscript.Wecanaccessthemessagepayload,wecanaccessthemessageheader.Withtestcontextaccesswecanalsosavethewholemessagepayloadasanewtestvariableforlaterusageinthetest.
IngeneralGroovycodeinsidetheXMLtestcasedefinitionoraspartoftheJavaDSLcodeisnotverycomfortabletomaintain.Youdonothavecodesyntaxassistorcodecompletion.Thisiswhywecanalsouseexternalfileresourcesforthevalidationscripts.Thesyntaxlookslikefollows:
XMLDSL
<receiveendpoint="helloServiceClient"timeout="5000"><message><validate><scripttype="groovy"file="classpath:validationScript.groovy"/></validate></message><header><elementname="Operation"value="sayHello"/><elementname="CorrelationId"value="$correlationId"/></header></receive>
JavaDSLdesigner
@CitrusTestpublicvoidreceiveMessageTest()receive("helloServiceClient").validateScript(newFileSystemResource("validationScript.groovy")).header("Operation,"sayHello").header("CorrelationId","$correlationId").timeout(5000L);
CitrusReferenceGuide
73Xml
![Page 74: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/74.jpg)
WereferencedsomeexternalfileresourcevalidationScript.groovy.Thisfilecontentisloadedatruntimeandisusedasscriptbody.NowthatwehaveanormalgroovyfilewecanusethecodecompletionandsyntaxhighlightingofourfavoriteGroovyeditor.
NoteYoucanusetheGroovyvalidationscriptincombinationwithothervalidationtypeslikeXMLtreecomparisonandXPathvalidation.TipForfurtherinformationontheGroovyXmlSlurperpleaseseetheofficialGroovywebsiteanddocumentation
CitrusReferenceGuide
74Xml
![Page 75: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/75.jpg)
XMLschemavalidation
ThereareseveralpossibilitiestodescribethestructureofXMLdocuments.ThetwomostpopularwaysareDTD(Documenttypedefinition)andXSD(XMLSchemadefinition).OnceaXMLdocumenthasdecidedtobeclassifiedusingaschemadefinitionthestructureofthedocumenthastofitthepredefinedrulesinsidetheschemadefinition.XMLdocumentinstancesarevalidonlyincasetheymeetallthesestructurerulesdefinedintheschemadefinition.CurrentlyCitruscanvalidateXMLdocumentsusingtheschemalanguagesDTDandXSD.
XSDschemarepositories
CitrustriestovalidateallincomingXMLmessagesagainstaschemadefinitioninordertoensurethatallrulesarefulfilled.AsaconsequencethemessagereceivingactionsinCitrusdohavetoknowtheXMLschemadefinition(*.xsd)fileresourcesthatbelongtoourproject.ThereforeCitrusintroducesacentralschemarepositorycomponentwhichholdsallavailableXMLschemafilesforaproject.
<citrus:schema-repositoryid="schemaRepository"><citrus:schemas><citrus:schemaid="travelAgencySchema"location="classpath:citrus/flightbooking/TravelAgencySchema.xsd"/><citrus:schemaid="royalArilineSchema"location="classpath:citrus/flightbooking/RoyalAirlineSchema.xsd"/><citrus:referenceschema="smartArilineSchema"/></citrus:schemas></citrus:schema-repository>
<citrus:schemaid="smartArilineSchema"location="classpath:citrus/flightbooking/SmartAirlineSchema.xsd"/>
AsyoucanseetheschemarepositoryisasimpleXMLcomponentdefinedinsidetheSpringapplicationcontext.Therepositorycanholdnestedschemadefinitionsdefinedbysomeidentifierandafilelocationforthexsdschemafile.Schemadefinitionscanalsobereferencedbyitsidentifierforusageinseveralschemarepositoryinstances.
ByconventionthedefaultschemarepositorycomponentisdefinedintheCitrusSpringapplicationcontextwiththeidschemaRepository.Springapplicationcontextisthenabletoinjecttheschemarepositoryintoallmessagereceivingtestactionsatruntime.ThereceivingtestactionconsolidatestherepositoryforamatchingschemadefinitionfileinordertovalidatetheincomingXMLdocumentstructure.
CitrusReferenceGuide
75Schema
![Page 76: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/76.jpg)
TheconnectionbetweenincomingXMLmessagesandxsdschemafilesintherepositoryisdonebyamappingstrategywhichwewilldiscusslaterinthischapter.BydefaultCitruspickstherightschemabasedonthetargetnamespacethatisdefinedinsidetheschemadefinition.ThetargetnamespaceoftheschemadefinitionhastomatchthenamespaceoftherootelementinthereceivedXMLmessage.WiththismappingstrategyyouwillnothavetowireXMLmessagesandschemafilesmanuallyallisdoneautomaticallybytheCitrusschemarepositoryatruntime.AllyouneedtodoistoregisterallavailableschemadefinitionfilesregardlessofwhichtargetnamespaceornatureinsidetheCitrusschemarepository.
ImportantXMlschemavalidationismandatoryinCitrus.ThismeansthatCitrusalwaystriestofindamatchingschemadefinitioninsidetheschemarepositoryinordertoperformsyntaxvalidationonincomingschemaqualifiedXMLmessages.AclassifiedXMLmessageisdefinedbyitsnamespacedefinitions.Consequentlyyouwillgetvalidationerrorsincasenomatchingschemadefinitionfileisfoundinsidetheschemarepository.SoifyouexplicitlydonotwanttovalidatetheXMLschemaforsomereasonyouhavetodisablethevalidationexplicitlyinyourtestwithschema-validation="false".
<receiveendpoint="httpMessageEndpoint"><messageschema-validation="false"><validate><xpathexpression="//ns1:TestMessage/ns1:MessageHeader/ns1:MessageId"value="$messageId"/><xpathexpression="//ns1:TestMessage/ns1:MessageHeader/ns1:CorrelationId"value="$correlationId"/><namespaceprefix="ns1"value="http://citrus.com/namespace"/></validate></message><header><elementname="Operation"value="sayHello"/><elementname="MessageId"value="$messageId"/></header></receive>
ThismandatoryschemavalidationmightsoundannoyingtoyoubutinouropinionitisveryimportanttovalidatethestructureofthereceivedXMLmessages,sodisablingtheschemavalidationshouldnotbethestandardforalltests.Disablingautomaticschemavalidationshouldonlyapplytoveryspecialsituations.Sopleasetrytoputallavailableschemadefinitionstotheschemarepositoryandyouwillbefine.
WSDLschemas
CitrusReferenceGuide
76Schema
![Page 77: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/77.jpg)
InSOAPWebServicesworldtheWSDL(WebServiceSchemaDefinitionLanguage)definesthestructureannatureoftheXMLmessagesexchangedacrosstheinterface.OftentheWSDLfilesdoholdtheXMLschemadefinitionsasnestedelements.InCitrusyoucandirectlysettheWSDLfileaslocationofaschemadefinitionlikethis:
<citrus:schemaid="arilineWsdl"location="classpath:citrus/flightbooking/AirlineSchema.wsdl"/>
CitrusisabletofindthenestedschemadefinitionsinsidetheWSDLfileinordertobuildavalidschemafilefortheschemarepository.SoincomingXMLmessagesthatrefertotheWSDLfilecanbevalidatedforsyntaxrules.
Schemalocationpatterns
Settingallschemasonebyoneinaschemarepositorycanbeverboseanduncomfortable,especiallywhendealingwithlotsofxsdandwsdlfiles.Theschemarepositoryalsosupportslocationpatternexpressions.Seethisexampletoseehowitworks:
<citrus:schema-repositoryid="schemaRepository"><citrus:locations><citrus:locationpath="classpath:citrus/flightbooking/*.xsd"/></citrus:locations></citrus:schema-repository>
Theschemarepositorysearchesforallfilesmatchingtheresourcepathlocationpatternandaddsthemasschemainstancestotherepository.OfcoursethisalsoworkswithWSDLfiles.
Schemacollections
Sometimesmultipleaschemadefinitionisseparatedintomultiplefiles.ThisisaproblemfortheCitrusschemarepositoryastheschemamappingstrategythenisnotabletopicktherightfileforvalidation,inparticularwhenworkingwithtargetnamespacevaluesaskeyfortheschemamappingstrategy.Asasolutionforthisproblemyouhavetoputallschemaswiththesametargetnamespacevalueintoaschemacollection.
<citrus:schema-collectionid="flightbookingSchemaCollection"><citrus:schemas>
CitrusReferenceGuide
77Schema
![Page 78: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/78.jpg)
<citrus:schemalocation="classpath:citrus/flightbooking/BaseTypes.xsd"/><citrus:schemalocation="classpath:citrus/flightbooking/AirlineSchema.xsd"/></citrus:schemas></citrus:schema-collection>
BothschemadefinitionsBaseTypes.xsdandAirlineSchema.xsdsharethesametargetnamespaceandthereforeneedtobecombinedinschemacollectioncomponent.Theschemacollectioncanbereferencedinanyschemarepositoryasnormalschemadefinition.
<citrus:schema-repositoryid="schemaRepository"><citrus:schemas><citrus:referenceschema="flightbookingSchemaCollection"/></citrus:schemas></citrus:schema-repository>
Schemamappingstrategy
TheschemarepositoryinCitrusholdsonetomanyschemadefinitionfilesanddynamicallypicksuptherightoneaccordingtothevalidatedmessagepayload.Therepositoryneedstohavesomestrategyfordecidingwhichschemadefinitiontochoose.Seethefollowingschemamappingstrategiesanddecidewhichofthemissuitableforyou.
TargetNamespaceMappingStrategy
Thisisthedefaultschemamappingstrategy.Schemadefinitionsusuallydefinesometargetnamespacewhichisvalidforallelementsandtypesinsidetheschemafile.ThetargetnamespaceisalsousedasrootnamespaceinXMLmessagepayloads.AccordingtothisinformationCitruscanpickuptherightschemadefinitionfileintheschemarepository.Youcansettheschemamappingstrategyaspropertyintheconfigurationfiles:
<citrus:schema-repositoryid="schemaRepository"schema-mapping-strategy="schemaMappingStrategy"><citrus:schemas><citrus:schemaid="helloSchema"location="classpath:citrus/samples/sayHello.xsd"/></citrus:schemas></citrus:schema-repository>
<beanid="schemaMappingStrategy"
CitrusReferenceGuide
78Schema
![Page 79: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/79.jpg)
class="com.consol.citrus.xml.schema.TargetNamespaceSchemaMappingStrategy"/>
ThesayHello.xsdschemafiledefinesatargetnamespace(http://consol.de/schemas/sayHello.xsd):
<xs:schemaxmlns:xs="http://www.w3.org/2001/XMLSchema"xmlns="http://consol.de/schemas/sayHello.xsd"targetNamespace="http://consol.de/schemas/sayHello.xsd"elementFormDefault="qualified"attributeFormDefault="unqualified">
</xs:schema>
IncomingrequestmessagesshouldalsohavethetargetnamespacesetintherootelementandthisishowCitrusmatchestherightschemafileintherepository.
<HelloRequestxmlns="http://consol.de/schemas/sayHello.xsd"><MessageId>123456789</MessageId><CorrelationId>1000</CorrelationId><User>Christoph</User><Text>HelloCitrus</Text></HelloRequest>
RootQNameMappingStrategy
ThenextpossibilityformappingincomingrequestmessagestoaschemadefinitionisviatheXMLrootelementQName.EachXMLmessagepayloadstartswitharootelementthatusuallydeclaresthetypeofaXMLmessage.Accordingtothisrootelementyoucansetupmappingsintheschemarepository.
<citrus:schema-repositoryid="schemaRepository"schema-mapping-strategy="schemaMappingStrategy"><citrus:schemas><citrus:referenceschema="helloSchema"/><citrus:referenceschema="goodbyeSchema"/></citrus:schemas></citrus:schema-repository>
<beanid="schemaMappingStrategy"class="com.consol.citrus.xml.schema.RootQNameSchemaMappingStrategy"><propertyname="mappings"><map><entrykey="HelloRequest"value="helloSchema"/><entrykey="GoodbyeRequest"value="goodbyeSchema"/>
CitrusReferenceGuide
79Schema
![Page 80: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/80.jpg)
</map></property></bean>
<citrus:schemaid="helloSchema"location="classpath:citrus/samples/sayHello.xsd"/>
<citrus:schemaid="goodbyeSchema"location="classpath:citrus/samples/sayGoodbye.xsd"/>
Thelistingabovedefinestworootqnamemappings-oneforHelloRequestandoneforGoodbyeRequestmessagetypes.Anincomingmessageoftypeisthenmappedtotherespectiveschemaandsoon.WiththisdedicatedmappingsyouareabletocontrolwhichschemaisusedonaXMLrequest,regardlessoftargetnamespacedefinitions.
Schemamappingstrategychain
Let'sdiscussthepossibilitytocombineseveralschemamappingstrategiesinalogicalchain.Youcandefinemorethanonemappingstrategythatareevaluatedinsequence.Thefirststrategytofindaproperschemadefinitionfileintherepositorywins.
<citrus:schema-repositoryid="schemaRepository"schema-mapping-strategy="schemaMappingStrategy"><citrus:schemas><citrus:referenceschema="helloSchema"/><citrus:referenceschema="goodbyeSchema"/></citrus:schemas></citrus:schema-repository>
<beanid="schemaMappingStrategy"class="com.consol.citrus.xml.schema.SchemaMappingStrategyChain"><propertyname="strategies"><list><beanclass="com.consol.citrus.xml.schema.RootQNameSchemaMappingStrategy"><propertyname="mappings"><map><entrykey="HelloRequest"value="helloSchema"/></map></property></bean><beanclass="com.consol.citrus.xml.schema.TargetNamespaceSchemaMappingStrategy"/></list></property></bean>
CitrusReferenceGuide
80Schema
![Page 81: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/81.jpg)
SotheschemamappingchainusesbothRootQNameSchemaMappingStrategyandTargetNamespaceSchemaMappingStrategyincombination.Incasethefirstrootqnamestrategyfailstofindapropermappingthenexttargetnamespacestrategycomesinandtriestofindaproperschema.
Schemadefinitionoverruling
Nowitistimetotalkaboutschemadefinitionsettingsontestactionlevel.WehavelearnedbeforethatCitrustriestoautomaticallyfindamatchingschemadefinitioninsomeschemarepository.Therecomesatimewhereyouasatesterjusthavetopicktherightschemadefinitionbyyourself.YoucanoverruleallschemamappingstrategiesinCitrusbydirectlysettingthedesiredschemainyourreceivingmessageaction.
<receiveendpoint="httpMessageEndpoint"><messageschema="helloSchema"><validate><xpathexpression="//ns1:TestMessage/ns1:MessageHeader/ns1:MessageId"value="$messageId"/><xpathexpression="//ns1:TestMessage/ns1:MessageHeader/ns1:CorrelationId"value="$correlationId"/><namespaceprefix="ns1"value="http://citrus.com/namespace"/></validate></message></receive>
<citrus:schemaid="helloSchema"location="classpath:citrus/samples/sayHello.xsd"/>
Intheexampleabovethetesterexplicitlysetsaschemadefinitioninthereceiveaction(schema="helloSchema").Theattributevaluereferstonamedschemabeansomewhereintheapplciationcontext.Thisoverrulesallschemamappingstrategiesusedinthecentralschemarepositoryasthegivenschemaisdirectlyusedforvalidation.Thisfeatureishelpfulwhendealingwithdifferentschemaversionsatthesametimewheretheschemarepositorycannothelpyouanymore.
Anotherpossibilitywouldbetosetacustomschemarepositoryatthispoint.ThismeansyoucanhavemorethanoneschemarepositoryinyourCitrusprojectandyoupicktherightonebyyourselfinthereceiveaction.
<receiveendpoint="httpMessageEndpoint"><messageschema-repository="mySpecialSchemaRepository"><validate><xpathexpression="//ns1:TestMessage/ns1:MessageHeader/ns1:MessageId"
CitrusReferenceGuide
81Schema
![Page 82: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/82.jpg)
value="$messageId"/><xpathexpression="//ns1:TestMessage/ns1:MessageHeader/ns1:CorrelationId"value="$correlationId"/><namespaceprefix="ns1"value="http://citrus.com/namespace"/></validate></message></receive>
Theschema-repositoryattributereferstoaCitrusschemarepositorycomponentwhichisdefinedsomewhereintheSpringapplicationcontext.
ImportantIncaseyouhaveseveralschemarepositoriesinyourprojectdoalwaysdefineadefaultrepository(name="schemaRepository").ThishelpsCitrustoalwaysfindatleastonerepositorytointeractwith.
DTDvalidation
XMLDTD(Documenttypedefinition)isanotherwaytovalidatethestructureofaXMLdocument.ManypeoplesaythatDTDisdeprecatedandXMLschemaisthemuchmoreefficientwaytodescribetherulesofaXMLstructure.Wedonotdisagreewiththat,butwealsoknowthatlegacysystemsmightstilluseDTD.SoinordertoavoidvalidationerrorswehavetodealwithDTDvalidationaswell.
FirstthingyoucandoaboutDTDvalidationistospecifyaninlineDTDinyourexpectedmessagetemplate.
<receiveendpoint="httpMessageEndpoint"><messageschema-validation="false"><data><![CDATA[<!DOCTYPEroot[<!ELEMENTroot(message)><!ELEMENTmessage(text)><!ELEMENTtext(#PCDATA)>]><root><message><text>HelloTestFramework!</text></message></root>]]><data/></message></receive>
CitrusReferenceGuide
82Schema
![Page 83: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/83.jpg)
ThesystemundertestmayalsosendthemessagewithainlineDTDdefinition.Sovalidationwillsucceed.
InmostcasestheDTDisreferencedasexternal.dtdfileresource.Youcandothisinyourexpectedmessagetemplateaswell.
<receiveendpoint="httpMessageEndpoint"><messageschema-validation="false"><data><![CDATA[<!DOCTYPErootSYSTEM"com/consol/citrus/validation/example.dtd"><root><message><text>HelloTestFramework!</text></message></root>]]><data/></message></receive>
CitrusReferenceGuide
83Schema
![Page 84: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/84.jpg)
JSONmessagevalidation
MessageformatssuchasJSONhavebecomeverypopular,inparticularwhenspeakingofRESTfulWebServicesandJavaScriptusingJSONasthemessageformattogofor.CitrusisabletoexpectandvalidateJSONmessagesaswewillseeinthenextsections.
ImportantBydefaultCitruswilluseXMLmessageformatswhensendingandreceivingmessages.ThisalsoreflectstothemessagevalidationlogicCitrususesforincomingmessages.SobydefaultCitruswilltrytoparsetheincomingmessageasXMLDOMelementtree.IncasewewouldliketoenableJSONmessagevalidationwehavetotellCitrusthatweexpectaJSONmessagerightnow.
Andthisisquiteeasy.CitrushasaJSONmessagevalidatorimplementationactivebydefaultandimmediatelyaswemarkanincomingmessageasJSONdatathismessagevalidatorwilljumpin.
CitrusprovidesseveraldefaultmessagevalidatorimplementationsforJOSNmessageformat:
com.consol.citrus.validation.json.JsonTextMessageValidator:BasicJSONmessagevalidatorimplementationcomparesJSONobjects(expectedandreceived).TheorderofJSONentriescandifferasspecifiedinJSONprotocol.TesterdefinesanexpectedcontrolJSONobjectwithtestvariablesandignoredentries.JSONArrayaswellasnestedJSONObjectsaresupported,too.TheJSONvalidatorofferstwodifferentmodestooperate.Bydefaultstrictmodeissetandthevalidatorwillalsochecktheexactamountofcontrolobjectfieldstomatch.NoadditionalfieldsinreceivedJSONdatastructurewillbeaccepted.InsoftmodevalidatorallowsadditionalfieldsinreceivedJSONdatastructuresothecontrolJSONobjectcanbeapartialsubsetinwhichcaseonlythecontrolfieldsarevalidated.AdditionalfieldsinthereceivedJSONdatastructureareignoredthen.
com.consol.citrus.validation.script.GroovyJsonMessageValidator:ExtendedgroovymessagevalidatorprovidesspecificJSONslurpersupport.WithJSONslurperthetestercanvalidatetheJSONmessagepayloadwithclosuresforinstance.
YoucanoverwritethisdefaultmessagevalidatorsforJSONbyplacingabeanintotheSpringApplicationcontext.Thebeanusesadefaultnameasidentifier.Thenyourcustombeanwilloverwritethedefaultvalidator:
<beanid="defaultJsonMessageValidator"class="com.consol.citrus.validation.json.JsonTextMessageValidator"
CitrusReferenceGuide
84Json
![Page 85: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/85.jpg)
<beanid="defaultGroovyJsonMessageValidator"class="com.consol.citrus.validation.script.GroovyJsonMessageValidator"
ThisishowyoucancustomizethemessagevalidatorsusedforJSONmessagedata.
WehavementionedbeforethatCitrusisworkingwithXMLbydefault.ThisiswhywehavetotellCitrusthatthemessagethatwearereceivingusestheJSONmessageformat.WehavetotellthetestcasereceivingactionthatweexpectadifferentformatotherthanXML.
<receiveendpoint="httpMessageEndpoint"><messagetype="json"><data>"type":"read","mbean":"java.lang:type=Memory","attribute":"HeapMemoryUsage","path":"@equalsIgnoreCase('USED')@","value":"$heapUsage","timestamp":"@ignore@"</data></message></receive>
Themessagereceivingactioninourtestcasespecifiesamessageformattypetype="json".ThistellsCitrustolookforsomemessagevalidatorimplementationcapableofvalidatingJSONmessages.AswehaveaddedthepropermessagevalidatortotheSpringapplicationcontextCitruswillpicktherightvalidatorandJSONmessagevalidationisperformedonthismessage.Asyoucanseeyouwecanusetheusualtestvariablesandtheignoreelementsyntaxhere,too.CitrusisabletohandledifferentJSONelementorderswhencomparingreceivedandexpectedJSONobject.WecanalsouseJSONarraysandnestedobjects.ThedefaultJSONmessagevalidatorimplementationinCitrusisverypowerfulincomparingJSONobjects.
InsteadofdefininganexpectedmessagepayloadtemplatewecanalsouseGroovyvalidationscripts.LetshavealookattheGroovyJSONmessagevalidatorexample.AsusualthedefaultGroovyJSONmessagevalidatorisactivebydefault.ButthespecialGroovymessagevalidatorimplementationwillonlyjumpinwhenweusedavalidationscriptinourreceivemessagedefinition.Let'shaveanexampleforthat.
CitrusReferenceGuide
85Json
![Page 86: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/86.jpg)
<receiveendpoint="httpMessageEndpoint"><messagetype="json"><validate><scripttype="groovy">
</script></validate></message></receive>
AgainwetellCitrusthatweexpectamessageoftype="json".NowweusedavalidationscriptthatiswritteninGroovy.CitruswillautomaticallyactivatethespecialmessagevalidatorthatexecutesourGroovyscript.ThescriptvalidationismorepowerfulaswecanusethefullpoweroftheGroovylanguage.ThevalidationscriptautomaticallyhasaccesstotheincomingJSONmessageobjectjson.WecanusetheGroovyJSONdotnotatedsyntaxinordertonavigatethroughtheJSONstructure.TheGroovyJSONslurperobjectjsonisautomaticallypassedtothevalidationscript.ThiswayyoucanaccesstheJSONobjectelementsinyourcodedoingsomeassertions.
Thereisevenmoreobjectinjectionforthevalidationscript.WiththeautomaticallyaddedobjectreceivedMessageYouhaveaccesstotheCitrusmessageobjectforthisreceiveaction.Thisenablesyoutodowhateveryouwantwiththemessagepayloadorheader.
XMLDSL
<receiveendpoint="httpMessageEndpoint"><messagetype="json"><validate><scripttype="groovy">assertreceivedMessage.getPayload(String.class).contains("HelloCitrus!")assertreceivedMessage.getHeader("Operation")=='sayHello'
context.setVariable("request_payload",receivedMessage.getPayload(String.class</script></validate></message></receive>
CitrusReferenceGuide
86Json
![Page 87: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/87.jpg)
Thelistingaboveshowssomepowerofthevalidationscript.Wecanaccessthemessagepayload,wecanaccessthemessageheader.Withtestcontextaccesswecanalsosavethewholemessagepayloadasanewtestvariableforlaterusageinthetest.
IngeneralGroovycodeinsidetheXMLtestcasedefinitionoraspartoftheJavaDSLcodeisnotverycomfortabletomaintain.Youdonothavecodesyntaxassistorcodecompletion.Thisiswhywecanalsouseexternalfileresourcesforthevalidationscripts.Thesyntaxlookslikefollows:
XMLDSL
<receiveendpoint="helloServiceClient"timeout="5000"><message><validate><scripttype="groovy"file="classpath:validationScript.groovy"/></validate></message></receive>
JavaDSLdesigner
@CitrusTestpublicvoidreceiveMessageTest()receive("helloServiceClient").validateScript(newFileSystemResource("validationScript.groovy"));
WereferencedsomeexternalfileresourcevalidationScript.groovy.Thisfilecontentisloadedatruntimeandisusedasscriptbody.NowthatwehaveanormalgroovyfilewecanusethecodecompletionandsyntaxhighlightingofourfavoriteGroovyeditor.
ImportantUsingseveralmessagevalidatorimplementationsatthesametimeintheSpringapplicationcontextisalsonoproblem.Citrusautomaticallysearchesforallavailablemessagevalidatorsapplicableforthegivenmessageformatandexecutesthesevalidatorsinsequence.SoseveralmessagevalidatorscancoexistinaCitrusproject.
WhenwehavemultiplemessagevalidatorsthatapplytothemessageformatCitruswillexecutealloftheminsequence.Incaseyouneedtoexplicitlychooseamessagevalidatorimplementationyoucandosointhereceiveaction:
<receiveendpoint="httpMessageEndpoint"><messagetype="json"validator="groovyJsonMessageValidator">
CitrusReferenceGuide
87Json
![Page 88: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/88.jpg)
<validate><scripttype="groovy">
</script></validate></message></receive>
InthisexampleweusethegroovyJsonMessageValidatorexplicitlyinthereceivetestaction.ThemessagevalidatorimplementationwasaddedasSpringbeanwithidgroovyJsonMessageValidatortotheSpringapplicationcontextbefore.NowCitruswillonlyexecutetheexplicitmessagevalidator.Otherimplementationsthatmightalsoapplyareskipped.
TipBydefaultCitruswillconsolidateallavailablemessagevalidatorsforamessageformatinsequence.Youcanexplicitlypickaspecialmessagevalidatorinthereceivemessageactionasshownintheexampleabove.Inthiscaseallothervalidatorswillnottakepartinthisspecialmessagevalidation.Butbecareful:Whenpickingamessagevalidatorexplicitlyyouareofcourselimitedtothismessagevalidatorcapabilities.Validationfeaturesofothervalidatorsarenotvalidinthiscase(e.g.messageheadervalidation,XPathvalidation,etc.)
SomuchforreceivingJSONmessagedatainCitrus.OfcoursesendingJSONmessagesinCitrusisalsoveryeasy.JustuseJSONmessagepayloadsinyoursendingmessageaction.
<sendendpoint="httpMessageEndpoint"><message><data>"type":"read","mbean":"java.lang:type=Memory","attribute":"HeapMemoryUsage","path":"used"</data></message></send>
CitrusReferenceGuide
88Json
![Page 89: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/89.jpg)
CitrusReferenceGuide
89Json
![Page 90: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/90.jpg)
XHTMLmessagevalidation
WhenCitrusreceivesplainHtmlmessageswelikelywanttousethepowerfulXMLvalidationcapabilitiessuchasXMLtreecomparisonorXPathsupport.UnfortunatelyHtmlmessagesdonotfollowtheXMLwellformedrulesverystrictly.ThisimpliesthatXMLmessagevalidationwillfailbecauseofnonwellformedHtmlcode.
XHTMLclosesthisgapbyautomaticallyfixingthemostcommonHtmlXMLincompatibleruleviolationssuchasmissingendtags(e.g.).
Let'strythiswithasimpleexample.Veryfirstthingforustodoistoaddanewlibrarydependencytotheproject.CitrusisusingthejtidylibraryinordertopreparetheHTMLandXHTMLmessagesforvalidation.Asthis3rdpartydependencyisoptionalinCitruswehavetoadditnowtoourprojectdependencylist.JustaddthejtidydependencytoyourMavenprojectPOM.
<dependency><groupId>net.sf.jtidy</groupId><artifactId>jtidy</artifactId><version>r938</version></dependency>
Pleaserefertothejtidyprojectdocumentationforthelatestversions.Noweverythingisready.AsusualtheCitrusmessagevalidatorforXHTMLisactiveinbackgroundbydefault.YoucanoverwritethisdefaultimplementationbyplacingaSpringbeanwithiddefaultXhtmlMessageValidatortotheCitrusapplicationcontext.
<beanid="defaultXhtmlMessageValidator"class="com.consol.citrus.validation.xhtml.XhtmlMessageValidator"
NowwecantellthetestcasereceivingactionthatwewanttousetheXHTMLmessagevalidationinourtestcase.
<receiveendpoint="httpMessageEndpoint"><messagetype="xhtml"><data><![CDATA[<!DOCTYPEhtmlPUBLIC"-//W3C//DTDXHTML1.1//EN""org/w3c/xhtml/xhtml1-strict.dtd"><htmlxmlns="http://www.w3.org/1999/xhtml"><head>
CitrusReferenceGuide
90Xhtml
![Page 91: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/91.jpg)
<title>CitrusHelloWorld</title></head><body><h1>HelloWorld!</h1><br/><p>Thisisatest!</p></body>]]></data></message></receive>
Themessagereceivingactioninourtestcasehastospecifyamessageformattypetype="xhtml".AsyoucanseetheHtmlmessagepayloadgetXHTMLspecificDOCTYPEprocessinginstruction.Thexhtml1-strict.dtdismandatoryintheXHTMLmessagevalidation.ForbetterconvenienceallXHTMLdtdfilesarepackagedwithinCitrussoyoucanusethisasarelativepath.
TheincomingHtmlmessageisautomaticallyconvertedintoproperXHTMLcodewithwellformedXML.SonowtheXHTMLmessagevalidatorcanusetheXMLmessagevalidationmechanismofCitrusforcomparingreceivedandexpecteddata.Asusualyoucanusetestvariables,ignoreelementexpressionsandXPathexpressions.
CitrusReferenceGuide
91Xhtml
![Page 92: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/92.jpg)
Plaintextmessagevalidation
PlaintextmessagevalidationistheeasiestvalidationinCitrusthatyoucanthinkof.ThisvalidationjustperformsanexactJavaStringmatchofreceivedandexpectedmessagepayloads.
Asusualadefaultmessagevalidatorforplaintextmessagesisactivebydefault.Citruswillpickthismessagevalidatorforallmessagesoftype="plaintext".ThedefaultmessagevalidatorimplementationcanbeoverwrittenbyplacingaSpringbeanwithiddefaultPlaintextMessageValidatortotheSpringapplicationcontext.
<beanid="defaultPlaintextMessageValidator"class="com.consol.citrus.validation.text.PlainTextMessageValidator"
InthetestcasereceivingactionwetellCitrustouseplaintextmessagevalidation.
<receiveendpoint="httpMessageEndpoint"><messagetype="plaintext"><data>HelloWorld!</data></message></receive>
Withthemessageformattypetype="plaintext"setCitrusperformsStringequalsonthemessagepayloads(receivedandexpected).Onlyexactmatchwillpassthetest.
BythewaysendingplaintextmessagesinCitrusisalsoveryeasy.Justusetheplaintextmessagepayloaddatainyoursendingmessageaction.
<sendendpoint="httpMessageEndpoint"><message><data>HelloWorld!</data></message></send>
Ofcoursetestvariablesaresupportedintheplaintextpayloads.Thevariablesarereplacebythereferencedvaluesbeforesendingorreceivingthemessage.
Plaintextmessagepayloadsmayonlydifferinwhitespacese.g.newlinecharacters.Bydefaultthemessagevalidationfailsevenifonlywhitespacecharactersaredifferent.
CitrusReferenceGuide
92Plaintext
![Page 93: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/93.jpg)
Youcandisablethisdefaultbehaviorandignorewhitespacescharacterslikenewlineswithfollowingsystemproperty:
citrus.plaintext.validation.ignore.whitespace=true
Alsoyoucouldsetthepropertydirectlyonthemesagevalidatorbean:
<beanid="defaultPlaintextMessageValidator"class="com.consol.citrus.validation.text.PlainTextMessageValidator"<propertyname="ignoreWhitespace"value="true"/></bean>
CitrusReferenceGuide
93Plaintext
![Page 94: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/94.jpg)
Binarymessagevalidation
Binarymessagevalidationisnotveryeasytodoespeciallywhenitcomestocomparedatawithagivencontrolmessage.Asatesteryouwanttovalidatethebinarycontent.InCitrusthewaytocomparebinarymessagecontentistousebase64Stringencoding.Thebinarydataisencodedasbase64charactersequenceandthereforeiscomparablewithanexpectedcontent.
Thereceivedmessagecontentdoesnothavetobebase64encoded.Citrusisdoingthisconversionautomaticallybeforevalidationtakesplace.Thebinarydatacanbeanythinge.g.images,pdforgzipcontent.
Thedefaultmessagevalidatorforbinarymessagesisactivebydefault.Citruswillpickthismessagevalidatorforallmessagesoftype="binary_base64".ThedefaultmessagevalidatorimplementationcanbeoverwrittenbyplacingaSpringbeanwithiddefaultBinaryBase64MessageValidatortotheSpringapplicationcontext.
<beanid="defaultBinaryBase64MessageValidator"class="com.consol.citrus.validation.text.BinaryBase64MessageValidator"
InthetestcasereceivingactionwetellCitrustousebinarybase64messagevalidation.
<receiveendpoint="httpMessageEndpoint"><messagetype="binary_base64"><data>citrus:encodeBase64('HelloWorld!')</data></message></receive>
Withthemessageformattypetype="binary_base64"Citrusperformsthebase64charactersequencevalidation.Incomingmessagecontentisautomaticallyencodedasbase64Stringandcomparedtotheexpecteddata.Thiswaywecanmakesurethatthebinarycontentisasexpected.
BythewaysendingbinarymessagesinCitrusisalsoveryeasy.Justusethetype="binary"messagetypeinthesendoperation.Citrusnowconvertsthemessagepayloadtoabinarystreamaspayload.
<sendendpoint="httpMessageEndpoint"><messagetype="binary"><data>HelloWorld!</data></message>
CitrusReferenceGuide
94Binary
![Page 95: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/95.jpg)
</send>
Base64encodingisalsosupportedinoutboundmessages.JustusetheencodeBase64functioninCitrus.Theresultisabase64encodedStringasmessagepayload.
<sendendpoint="httpMessageEndpoint"><message><data>citrus:encodeBase64('HelloWorld!')</data></message></send>
CitrusReferenceGuide
95Binary
![Page 96: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/96.jpg)
Gzipmessagevalidation
Gzipisafamousmessagecompressionlibrary.Whendealingwithlargemessagecontentthecompressionmightbeagoodwaytooptimizethemessagetransportation.Citrusisabletohandlegzippedmessagepayloadsonsendandreceiveoperations.Whensendingcompresseddatawejusthavetousethemessagetypegzip.
<sendendpoint="messageEndpoint"><messagetype="gzip"><data>HelloWorld!</data></message></send>
Justusethetype="gzip"messagetypeinthesendoperation.Citrusnowconvertsthemessagepayloadtoagzipbinarystreamaspayload.
Whenvalidatinggzipbinarymessagecontentthemessagesarecomparedwithagivencontrolmessageinbinarybase64Stringrepresentation.Thegzipbinarydataisautomaticallyunzippedandencodedasbase64charactersequenceinordertocomparewithanexpectedcontent.
Thereceivedmessagecontentisusinggzipformatbuttheactualmessagecontentdoesnothavetobebase64encoded.Citrusisdoingthisconversionautomaticallybeforevalidationtakesplace.Thebinarydatacanbeanythinge.g.images,pdforplaintextcontent.
Thedefaultmessagevalidatorforgzipmessagesisactivebydefault.Citruswillpickthismessagevalidatorforallmessagesoftype="gzip_base64".ThedefaultmessagevalidatorimplementationcanbeoverwrittenbyplacingaSpringbeanwithiddefaultGzipBinaryBase64MessageValidatortotheSpringapplicationcontext.
<beanid="defaultGzipBinaryBase64MessageValidator"class="com.consol.citrus.validation.text.GzipBinaryBase64MessageValidator"
InthetestcasereceivingactionwetellCitrustousegzipmessagevalidation.
<receiveendpoint="messageEndpoint"><messagetype="gzip_base64"><data>citrus:encodeBase64('HelloWorld!')</data></message></receive>
CitrusReferenceGuide
96Gzip
![Page 97: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/97.jpg)
Withthemessageformattypetype="gzip_base64"Citrusperformsthegzipbase64charactersequencevalidation.Incomingmessagecontentisautomaticallyunzippedandencodedasbase64Stringandcomparedtotheexpecteddata.Thiswaywecanmakesurethatthebinarycontentisasexpected.
NoteIfyouareusinghttpclientandservercomponentsthegzipcompressionsupportisbuiltinwiththeunderlyingSpringandhttpcommonslibraries.SoinhttpcommunicationyoujusthavetosettheheaderAccept-Encoding=gziporContent-Encoding=gzip.Themessagedataisthenautomaticallyzipped/unzippedbeforeCitrusgetsthemessagedataforvalidation.Readmoreaboutthishttpspecificgzipcompressioninchapterhttp.
CitrusReferenceGuide
97Gzip
![Page 98: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/98.jpg)
UsingXPathSometimeagointhisdocumentwehavealreadyseenhowXMLmessagepayloadsareconstructedwhensendingandreceivingmessages.NowusingXPathisaverypowerfulwayofaccessingelementsincomplexXMLstructures.TheXPathexpressionlanguageisveryhandywhenitcomestosaveelementvaluesastestvariablesorwhenvalidatingspecialelementsinaXMLmessagestructure.
XPathisaverypowerfultechnologyforwalkingXMLtrees.ThisW3CstandardstandsforadvancedXMLtreehandlingusingaspecialsyntaxasquerylanguage.CitrussupportstheXPathsyntaxinthefollowingfields:
<message><elementpath="[XPath-Expression]"></message><validate><xpathexpression="[XPath-Expression]"/></validate><extract><messagepath="[XPath-Expression]"></extract><ignorepath="[XPath-Expression]"/>
ThenextprogramlistingindicatesthepowerinusingXPathwithCitrus:
<message><validate><xpathexpression="//User/Name"value="John"/><xpathexpression="//User/Address[@type='office']/Street"value="Companystreet21"/><xpathexpression="//User/Name"value="$userName"/><xpathexpression="//User/@isAdmin"value="$isAdmin"/><xpathexpression="//User/@isAdmin"value="true"result-type="boolean"/><xpathexpression="//*[.='search-for']"value="searched-for"/><xpathexpression="count(//orderStatus[.='success'])"value="3"result-type="number"/></validate></message>
NowwedescribetheXPathusageinCitrusstepbystep.
ManipulatewithXPath
SomeelementsinXMLmessagepayloadsmightbeofdynamicnature.Justthinkofgeneratedidentifiersortimestamps.Alsowedonotwanttorepeatthesamestaticidentifierseveraltimesinourtestcases.Thisisthetimewheretestvariablesanddynamicmessageelementoverwritecomeinhandy.Theideaissimple.Wewantto
CitrusReferenceGuide
98Xpath
![Page 99: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/99.jpg)
overwriteaspecificmessageelementinourpayloadwithadynamicvalue.ThiscanbedonewithXPathorinlinevariabledeclarations.Letshavealookatanexamplelistingshowingbothways:
XMLDSL
<message><payload><TestMessage><MessageId>$messageId</MessageId><CreatedBy>_</CreatedBy><VersionId>$version</VersionId></TestMessage></payload><elementpath="/TestMessage/CreatedBy"value="$user"/></message>
Theprogramlistingaboveshowswaysofsettingvariablevaluesinsideamessagetemplate.Firstofallyoucansimplyplacevariableexpressionsinsidethemessage(seehow$messageIdisused).InadditiontothatyoucanalsouseXPathexpressionstoexplicitlyoverwritemessageelementsbeforevalidation.
<elementpath="/TestMessage/CreatedBy"value="$user"/>
TheXPathexpressionevaluatesandsearchesfortherightelementinthemessagepayload.Thepreviouslydefinedvariable$userreplacestheelementvalue.OfcoursethisworkswithXMLattributestoo.
BothwaysviaXPathorinlinevariableexpressionsareequaltoeachother.WithrespecttothecomplexityofXMLnamespacesandXPathyoumayfindtheinlinevariableexpressionmorecomfortabletouse.Anywayfeelfreetochoosethewaythatfitsbestforyou.Thisishowwecanadddynamicvariablevaluestothecontroltemplateinordertoincreasemaintainabilityandrobustnessofmessagevalidation.
TipValidationmatchersputvalidationmechanismstoanewlevelofferingdynamicassertionstatementsforvalidation.Havealookatthepossibilitieswithassertionstatementsinvalidation-matchers###ValidatewithXPath
WehavealreadyseenhowtovalidatewholeXMLstructureswithcontrolmessagetemplates.Allelementsarevalidatedandcomparedoneafteranother.Insomecasesthisapproachmightbetooextensive.Imaginethetesteronlyneedstovalidateasmall
CitrusReferenceGuide
99Xpath
![Page 100: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/100.jpg)
subsetofmessageelements.Thedefinitionofcontroltemplatesincombinationwithseveralignorestatementsisnotappropriateinthiscase.Youwouldratherwanttouseexplicitelementvalidation.
XMLDSL
<message><validate><xpathexpression="/TestRequest/MessageId"value="$messageId"/><xpathexpression="/TestRequest/VersionId"value="2"/></validate></message>
JavaDSLdesigner
@CitrusTestpublicvoidreceiveMessageTest()receive("helloServiceServer").validate("/TestRequest/MessageId","$messageId").validate("//VersionId","2").header("Operation","sayHello");
InsteadofcomparingthewholemessagesomemessageelementsarevalidatedexplicitlyviaXPath.CitrusevaluatestheXPathexpressiononthereceivedmessageandcomparestheresultvaluetothecontrolvalue.Thebasicmessagestructureaswellasallothermessageelementsarenotincludedintothisexplicitvalidation.
NoteIfthistypeofelementvalidationischosenneithernornortemplatedefinitionsareallowedinCitrusXMLtestcases.
TipCitrusoffersanalternativedot-notatedsyntaxinordertowalkthroughXMLtrees.IncaseyouarenotfamiliarwithXPathorsimplyneedaveryeasywaytofindyourelementinsidetheXMLtreeyoumightusethisway.EveryelementhierarchyintheXMLtreeisrepresentedwithasimpledot-forexample:
TestRequest.VersionId
TheexpressionwillsearchtheXMLtreefortherespectiveelement.Attributesaresupportedtoo.Incasethelastelementinthedot-notatedexpressionisaXMLattributetheframeworkwillautomaticallyfindit.
CitrusReferenceGuide
100Xpath
![Page 101: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/101.jpg)
Ofcoursethisdot-notatedsyntaxisverysimpleandmightnotbeapplicableformorecomplextreenavigation.XPathismuchmorepowerful-nodoubt.Howeverthedot-notatedsyntaxmighthelpthoseofyouthatarenotfamiliarwithXPath.Sothedot-notationissupportedwhereverXPathexpressionsmightapply.
TheXpathexpressionscanevaluatetodifferentresulttypes.BydefaultCitrusisoperatingonNODEandSTRINGresulttypessothatyoucanvalidatesomeelementvalue.ButyoucanalsousedifferentresulttypessuchasNODESETandBOOLEAN.Seethisexamplehowthatworks:
XMLDSL
<message><validate><xpathexpression="/TestRequest/Error"value="false"result-type="boolean"/><xpathexpression="/TestRequest/Status[.='success']"value="3"result-type="number"/><xpathexpression="/TestRequest/OrderType"value="[single,multi,multi]"result-type="node-set"</validate></message>
JavaDSLdesigner
@CitrusTestpublicvoidreceiveMessageTest()receive("helloServiceServer").validate("boolean:/TestRequest/Error",false).validate("number:/TestRequest/Status[.='success']",3).validate("node-set:/TestRequest/OrderType","[single,multi,multi]").header("Operation","sayHello");
Intheexampleaboveweusedifferentexpressionresulttypes.Firstwewanttomakesurenor/TestRequest/Errorelementispresent.Thiscanbedonewithabooleanresulttypeandfalsevalue.Secondwewanttovalidatethenumberoffoundelementsfortheexpression/TestRequest/Status[.='success'].TheXPathexpressionevaluatestoanodelistthatresultsinitslistsizetobechecked.Andlastnotleastweevaluatetoanode-setresulttypewhereallvaluesinthenodelistwillbetranslatedtoacommadelimitedstringvalue.
Nowletshavealookatsomemorepowerfulvalidationexpressionsusingmatcherimplementations.UptonowwehaveseenthatXPathexpressionresultsarecomparablewithequalTooperations.Wewouldliketoaddsomemorepowerful
CitrusReferenceGuide
101Xpath
![Page 102: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/102.jpg)
validationsuchasgreaterThan,lessThan,hasSizeandmuchmore.ThereforewehaveintroducedHamcrestvalidationmatchersupportinCitrus.Hamcrestisaverypowefulmatcherlibrarythatprovidesafantasticsetofmatcherimplementations.Letsseehowwecanaddtheseinourtestcase:
XMLDSL
<message><validate><xpathexpression="/TestRequest/Error"value="@assertThat(anyOf(empty(),nullValue()))@"/><xpathexpression="/TestRequest/Status[.='success']"value="@assertThat(greaterThan(0))@"<xpathexpression="/TestRequest/OrderType"value="@assertThat(hasSize(3))@"result-type="node-set"</validate></message>
JavaDSLdesigner
@CitrusTestpublicvoidreceiveMessageTest()receive("helloServiceServer").validate("/TestRequest/Error",anyOf(empty(),nullValue())).validate("number:/TestRequest/Status[.='success']",greaterThan(0)).validate("node-set:/TestRequest/OrderType",hasSize(3)).header("Operation","sayHello");
WhenusingtheXMLDSLwehavetousetheassertThatvalidationmatchersyntaxfordefiningtheHamcrestmatchers.YoucancombinematcherimplementationasseenintheanyOf(empty(),nullValue())expression.WhenusingtheJavaDSLyoucanjustaddthematcherasexpectedresultobject.Citrusevaluatesthematchersandmakessureeverythingisasexpected.Thisisaverypowerfulvalidationmechanismasitalsoworkswithnode-setscontainingmultiplevaluesaslist.
ThisishowyoucanaddverypowerfulmessageelementvalidationinXMLusingXPathexpressions.
ExtractvariableswithXPath
Imagineyoureceiveamessageinyourtestwithsomegeneratedmessageidentifiervalues.Youhavenochancetopredicttheidentifiervaluebecauseitwasgeneratedatruntimebyaforeignapplication.Youcanignorethevalueinordertoprotectyourvalidation.Butinmanycasesyoumightneedtoreturnthisidentifierintherespective
CitrusReferenceGuide
102Xpath
![Page 103: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/103.jpg)
responsemessageorsomewhatlateroninthetest.Sowehavetosavethedynamicmessagecontentforreuseinlaterteststeps.Thesolutionissimpleandverypowerful.Wecanextractdynamicvaluesfromreceivedmessagesandsavethosetotestvariables.Addthiscodetoyourmessagereceivingaction.
XMLDSL
<extract><headername="Operation"variable="operation"/><messagepath="/TestRequest/VersionId"variable="versionId"/></extract>
JavaDSLdesigner
@CitrusTestpublicvoidreceiveMessageTest()receive("helloServiceServer").extractFromHeader("Operation","operation").extractFromPayload("//TestRequest/VersionId","versionId");
echo("Extractedoperationfromheaderis:$operation");echo("Extractedversionfrompayloadis:$versionId");
AsyoucanseeCitrusisabletoextractbothheaderandmessagepayloadcontentintotestvariables.Itdoesnotmatterifyouusenewtestvariablesorexistingvariablesastarget.Theextractionwillautomaticallycreateanewvariableincaseitdoesnotexist.Thetimethevariablewascreatedallfollowingtestactionscanaccessthetestvariablesasusual.Soyoucanreferencethevariablevaluesinresponsemessagesorotherteststepsahead.
TipWecanalsouseexpressionresulttypesinordertomanipulatethetestvariableoutcome.Incaseweuseabooleanresulttypetheexistenceofelementscanbesavedtovariablevalues.Theresulttypenode-settranslatesanodelistresulttoacommaseparatedstringofallvaluesinthisnodelist.Simplyusetheexpressionresulttypeattributesasshowninprevioussections.
XMLnamespacesinXPath
WhenitcomestoXMLnamespacesyouhavetobecarefulwithyourXPathexpressions.LetshavealookatanexamplemessagethatusesXMLnamespaces:
CitrusReferenceGuide
103Xpath
![Page 104: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/104.jpg)
<ns1:TestMessagexmlns:ns1="http://citrus.com/namespace"><ns1:TestHeader><ns1:CorrelationId>_</ns1:CorrelationId><ns1:Timestamp>2001-12-17T09:30:47.0Z</ns1:Timestamp><ns1:VersionId>2</ns1:VersionId></ns1:TestHeader><ns1:TestBody><ns1:Customer><ns1:Id>1</ns1:Id></ns1:Customer></ns1:TestBody></ns1:TestMessage>
NowwewouldliketovalidatesomeelementsinthismessageusingXPath
<message><validate><xpathexpression="//TestMessage/TestHeader/VersionId"value="2"/><xpathexpression="//TestMessage/TestHeader/CorrelationId"value="$correlationId"/></validate></message>
ThevalidationwillfailalthoughtheXPathexpressionlookscorrectregardingtheXMLtree.Becausethemessageusesthenamespacexmlns:ns1="http://citrus.com/namespace"withitsprefixns1ourXPathexpressionisnotabletofindtheelements.ThecorrectXPathexpressionusesthenamespaceprefixasdefinedinthemessage.
<message><validate><xpathexpression="//ns1:TestMessage/ns1:TestHeader/ns1:VersionId"value="2"/><xpathexpression="//ns1:TestMessage/ns1:TestHeader/ns1:CorrelationId"value="$correlationId"</message>
Nowtheexpressionsworkfineandthevalidationissuccessful.Butthisisquiteerrorprone.Thisisbecausethetestisnowdependingonthenamespaceprefixthatisusedbysomeapplication.Assoonasthemessageissentwithadifferentnamespaceprefix(e.g.ns2)thevalidationwillfailagain.
Youcanavoidthiseffectwhenspecifyingyourownnamespacecontextandyourownnamespaceprefixduringvalidation.
CitrusReferenceGuide
104Xpath
![Page 105: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/105.jpg)
<message><validate><xpathexpression="//pfx:TestMessage/pfx:TestHeader/pfx:VersionId"value="2"/><xpathexpression="//pfx:TestMessage/pfx:TestHeader/pfx:CorrelationId"value="$correlationId"<namespaceprefix="pfx"value="http://citrus.com/namespace"/></validate></message>
Nowthetestinindependentfromanynamespaceprefixinthereceivedmessage.Thenamespacecontextwillresolvethenamespacesandfindtheelementsalthoughthemessagemightusedifferentprefixes.Theonlythingthatmattersisthatthenamespacevalue(http://citrus.com/namespace)matches.
TipInsteadofthisnamespacecontextonvalidationlevelyoucanalsohaveaglobalnamespacecontextwhichisvalidinalltestcases.WejustaddabeaninthebasicSpringapplicationcontextconfigurationwhichdefinesglobalnamespacemappings.
<namespace-context><namespaceprefix="def"uri="http://www.consol.de/samples/sayHello"/></namespace-context>
OncedefinedthedefnamespaceprefixisvalidinalltestcasesandallXPathexpressions.Thisenablesyoutofreeyourtestcasesfromnamespaceprefixbindingsthatmightbebrokenwithtime.YoucanusetheseglobalnamespacemappingswhereverXPathexpressionsarevalidinsideatestcase(validation,ignore,extract).
DefaultnamespacesinXPath
IntheprevioussectionwehaveseenthatXMLnamespacescangettrickywithXPathvalidation.Defaultnamespacescandoevenmore!Soletslookattheexamplewithdefaultnamespaces:
<TestMessagexmlns="http://citrus.com/namespace"><TestHeader><CorrelationId>_</CorrelationId><Timestamp>2001-12-17T09:30:47.0Z</Timestamp><VersionId>2</VersionId></TestHeader><TestBody><Customer><Id>1</Id></Customer>
CitrusReferenceGuide
105Xpath
![Page 106: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/106.jpg)
</TestBody></TestMessage>
Themessageusesdefaultnamespaces.ThefollowingapproachinXPathwillfailduetonamespaceproblems.
<message><validate><xpathexpression="//TestMessage/TestHeader/VersionId"value="2"/><xpathexpression="//TestMessage/TestHeader/CorrelationId"value="$correlationId"/></validate></message>
EvendefaultnamespacesneedtobespecifiedintheXPathexpressions.Lookatthefollowingcodelistingthatworksfinewithdefaultnamespaces:
<message><validate><xpathexpression="//:TestMessage/:TestHeader/:VersionId"value="2"/><xpathexpression="//:TestMessage/:TestHeader/:CorrelationId"value="$correlationId"/></validate></message>
TipItisrecommendedtousethenamespacecontextasdescribedinthepreviouschapterwhenvalidating.Onlythisapproachensuresflexibilityandstabletestcasesregardingnamespacechanges.
CitrusReferenceGuide
106Xpath
![Page 107: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/107.jpg)
UsingJSONPathJSONPathistheJSONequivalenttoXPathintheXMLmessageworld.WithJSONPathexpressionsyoucanqueryandmanipulateentriesofaJSONmessagestructure.TheJSONPathexpressionsevaluateagainstaJSONmessagewheretheJSONobjectstructureisrepresentedinadotnotatedsyntax.
YouwillseethatJSONPathisaverypowerfultechnologywhenitcomestofindobjectentriesinacomplexJSONhierarchystructure.AlsoJSONPathcanhelptodomessagemanipulationsbeforeamessageissentoutforinstance.CitrussupportsJSONPathexpressionsinvariousscenarios:
<message><elementpath="[JSONPath-Expression]"></message><validate><json-pathexpression="[JSONPath-Expression]"/></validate><extract><messagepath="[JSONPath-Expression]"></extract><ignorepath="[JSONPath-Expression]"/>
ManipulatewithJSONPath
FirstthingwewanttodowithJSONPathistomanipulateamessagecontentbeforeitisactuallysentout.Thisisveryusefulwhenworkingwithmessagefileresourcesthatarereusedaccrossmultipletestcases.EachtestcasecanmanipulatethemessagecontentindividuallywithJSONPathbeforesending.Letshavealookatthissimplesample:
<messagetype="json"><resourcefile="file:path/to/user.json"/><elementpath="$.user.name"value="Admin"/><elementpath="$.user.admin"value="true"/><elementpath="$..status"value="closed"/></message>
Weuseabasicmessagecontentfilethatiscalleduser.json.ThecontentofthefileisfollowingJSONdatastructure:
user:"id":citrus:randomNumber(10)"name":"Unknown","admin":"?","projects":
CitrusReferenceGuide
107JsonPath
![Page 108: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/108.jpg)
["name":"Project1","status":"open","name":"Project2","status":"open","name":"Project3","status":"closed"]
Citrusloadsthefilecontentanduseditasmessagepayload.BeforethemessageissentouttheJSONPathexpressionshavethechancetomanipulatethemessagecontent.AllJSONPathexpressionsareevaluatedandthegivevaluesoverwriteexistingvaluesaccordingly.Theresultingmessagelookslikefollows:
user:"id":citrus:randomNumber(10)"name":"Admin","admin":"true","projects":["name":"Project1","status":"closed","name":"Project2","status":"closed","name":"Project3","status":"closed"]
TheJSONPathexpressionshavesettheusernametoAdmin.Theadminbooleanpropertywassettotrueandallprojectstatusvaluesweresettoclosed.Nowthemessageisreadytobesentout.IncaseaJSONPathexpressionshouldfailtofindamatchingelementwithinthemessagestructurethetestcasewillfail.
CitrusReferenceGuide
108JsonPath
![Page 109: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/109.jpg)
WiththisJSONPathmechanismouareabletomanipulatemessagecontentbeforeitissentorreceivedwithinCitrus.Thismakeslifeveryeasywhenusingmessageresourcefilesthatarereusedacrossmultipletestcases.
ValidatewithJSONPath
LetscontinuetouseJSONPathexpressionswhenvalidatingareceivemessageinCitrus:
XMLDSL
<messagetype="json"><validate><json-pathexpression="$.user.name"value="Penny"/><json-pathexpression="$['user']['name']"value="$userName"/><json-pathexpression="$.user.aliases"value="["penny","jenny","nanny"]"/><json-pathexpression="$.user[?(@.admin)].password"value="@startsWith('$%00')@"/><json-pathexpression="$.user.address[?(@.type='office')]"value=""city":"Munich","street":"CompanyStreet","type":"office""/></validate></message>
JavaDSL
receive(someEndpoint).messageType(MessageType.JSON).validate("$.user.name","Penny").validate("$['user']['name']","$userName").validate("$.user.aliases","["penny","jenny","nanny"]").validate("$.user[?(@.admin)].password","@startsWith('$%00')@").validate("$.user.address[?(@.type='office')]",""city":"Munich","street":"CompanyStreet","type":"office"");
TheaboveJSONPathexpressionswillbeevaluatedwhenCitrusvalidatesthereceivedmessage.Theexpressionresultiscomparedtotheexpectedvaluewhereexpectationscanbestaticvaluesaswellastestvariablesandvalidationmatcherexpressions.IncaseaJSONPathexpressionshouldnotbeabletofindanyelementsthetestcasewillalsofail.
JSONisaprettysimpleyetpowerfulmessageformat.SimplifiedaJSONmessagejustknowsJSONObject,JSONArrayandJSONValueitems.ThehandlingofJSONObjectandJSONValueitemsinJSONPathexpressionsisstraightforward.Wejustuseadot
CitrusReferenceGuide
109JsonPath
![Page 110: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/110.jpg)
notatedsyntaxforwalkingthroughtheJSONObjecthierarchy.ThehandlingofJSONArrayitemsisalsonotverydifficulteither.CitruswilltrythebesttoconvertJSONArrayitemstoStringrepresentationvaluesforcomparison.
ImportantJSONPathexpressionswillonlyworkonJSONmessageformats.ThisiswhywehavetotellCitrusthecorrectmessageformat.BydefaultCitrusisworkingwithXMLmessagedataandthereforetheXMLvalidationmechanismsdoapplybydefault.WiththemessagetypeattributesettojsonwemakesurethatCitrusenablesJSONspecificfeaturesonthemessagevalidationsuchasJSONPathsupport.
NowletsgetabitmorecomplexwithvalidationmatchersandJSONobjectfunctions.CitrustriestogiveyouthemostcomfortablevalidationcapabilitieswhencomparingJSONobjectvaluesandJSONarrays.OnefirstthingyoucanuseisobjectfunctionslikekeySet()orsize().ThesefunctionalityisnotcoveredbyJSONPathoutofthebowbutaddedbyCitrus.Sethefollowingexampleonhowtouseit:
XMLDSL
<messagetype="json"><validate><json-pathexpression="$.user.keySet()"value="[id,name,admin,projects]"/><json-pathexpression="$.user.aliases.size()"value="3"/></validate></message>
JavaDSL
receive(someEndpoint).messageType(MessageType.JSON).validate("$.user.keySet()","[id,name,admin,projects]").validate("$.user.aliases.size()","3");
TheobjectfunctionsdoreturnspecialJSONobjectrelatedpropertiessuchasthesetofkeysforanobjectorthesizeofanJSONarray.
Nowletsgetevenmorecomfortablevalidationcapabilitieswithmatchers.CitrussupportsHamcrestmatcherswhichgivesusaverypowerfulwayofvalidatingJSONobjectelementsandarrays.Seethefollowingexamplesthatdemonstratehowthisworks:
XMLDSL
<messagetype="json">
CitrusReferenceGuide
110JsonPath
![Page 111: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/111.jpg)
<validate><json-pathexpression="$.user.keySet()"value="@assertThat(contains(id,name,admin,projects))@"<json-pathexpression="$.user.aliases.size()"value="@assertThat(allOf(greaterThan(0),lessThan(5)))@"</validate></message>
JavaDSL
receive(someEndpoint).messageType(MessageType.JSON).validate("$.user.keySet()",contains("id","name","admin","projects")).validate("$.user.aliases.size()",allOf(greaterThan(0),lessThan(5)));
WhenusingtheXMLDSLwehavetousetheassertThatvalidationmatchersyntaxfordefiningtheHamcrestmatchers.YoucancombinematcherimplementationasseenintheallOf(greaterThan(0),lessThan(5))expression.WhenusingtheJavaDSLyoucanjustaddthematcherasexpectedresultobject.Citrusevaluatesthematchersandmakessureeverythingisasexpected.ThisisaverypowerfulvalidationmechanismasitcombinestheHamcrestmatchercapabilitieswithJSONmessagevalidation.
ExtractvariableswithJSONPath
Citrusisabletosavemessagecontenttotestvariablesattestruntime.Whenanincomingmessageispassingthemessagevalidationtheusercanextractsomevaluesofthatreceivedmessagetonewtestvariablesforlateruseinthetest.Thisisespeciallyhandsomewhenhavingtosendbacksomedynamicvalues.SoletssavesomevaluesusingJSONPath:
<messagetype="json"><data>user:"name":"Admin","password":"secret","admin":"true","aliases":["penny","chef","master"]</data><extract><messagepath="$.user.name"variable="userName"/><messagepath="$.user.aliases"variable="userAliases"/><messagepath="$.user[?(@.admin)].password"variable="adminPassword"/>
CitrusReferenceGuide
111JsonPath
![Page 112: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/112.jpg)
</extract></message>
WiththisexamplewehaveextractedthreenewtestvariablesviaJSONPathexpressionevaluation.Thethreetestvariableswillbeavailabletoallupcomingtestactions.Thevariablevaluesare:
userName=AdminuserAliases=["penny","chef","master"]adminPassword=secret
AsyoucanseewecanalsoextractcomplexJSONObjectitemsorJSONArrayitems.ThetestvariablevalueisaStringrepresentationofthecomplexobject.
IgnorewithJSONPath
ThenextusagescenarioforJSONPathexpressionsinCitrusistheignoringofelementsduringmessagevalidation.AsyoualreadyknowCitrusprovidespowerfulvalidationmechanismsforXMLandJSONmessageformat.Theframeworkisabletocomparereceivedandexpectedmessagecontentswithpowerfulvalidatorimplementations.NowitthistimewewanttouseaJSONPathexpressionforignoringaveryspecificentryintheJSONobjectstructure.
<messagetype="json"><data>"users":["name":"Jane","token":"?","lastLogin":0,"name":"Penny","token":"?","lastLogin":0,"name":"Mary","token":"?","lastLogin":0]</data><ignoreexpression="$.users[*].token"/>
CitrusReferenceGuide
112JsonPath
![Page 113: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/113.jpg)
<ignoreexpression="$..lastLogin"/></message>
ThistimeweaddJSONPathexpressionsasignorestatements.Thismeansthatweexplicitlyleaveouttheevaluatedelementsfromvalidation.Obviouslythismechanismisagoodthingtodowhendynamicmessagedatasimplyisnotdeterministicsuchastimestampsanddynamicidentifiers.IntheexampleaboveweexplicitlyskipthetokenentryandalllastLoginvaluesthatareobviouslytimestampvaluesinmilliseconds.
TheJSONPathevaluationisverypowerfulwhenitcomestoselectasetofJSONobjectsandelements.ThisishowwecanignoreseveralelementswithonesingleJSONPathexpressionwhichisverypowerful.
CitrusReferenceGuide
113JsonPath
![Page 114: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/114.jpg)
TestactionsThischaptergivesabriefdescriptiontoalltestactionsthatatestercanincorporateintothetestcase.Besidessendingandreceivingmessagesthetestermayaccesstheseactionsinordertobuildamorecomplextestscenariothatfitsthedesiredusecase.
CitrusReferenceGuide
114Actions
![Page 115: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/115.jpg)
Sendingmessages
Inaintegrationtestscenariowewanttotriggerprocessesandcallinterfaceservicesonthesystemundertest.Inordertodothisweneedtobeabletosendmessagestovariousmessagetransports.ThereforethesendmessagetestactioninCitrusisoneofthemostimportanttestactions.FirstofallletushavealookattheCitrusmessagedefinitioninCitrus:
Amessageconsistsofamessageheader(name-valuepairs)andamessagepayload.Laterinthissectionwewillseedifferentwaysofconstructingamessagewithpayloadandheadervalues.Butfirstofalllet'sconcentrateonasimplesendingmessageactioninsideatestcase.
XMLDSL
<testcasename="SendMessageTest"><description>Basicsendmessageexample</description>
<variables><variablename="text"value="HelloCitrus!"/><variablename="messageId"value="Mx1x123456789"/></variables>
<actions><sendendpoint="helloServiceEndpoint"><messagename="helloMessage">
CitrusReferenceGuide
115Send
![Page 116: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/116.jpg)
<payload><TestMessage><Text>$text</Text></TestMessage></payload></message><header><elementname="Operation"value="sayHello"/><elementname="MessageId"value="$messageId"/></header></send></actions></testcase>
Themessagenameisoptionalanddefinesthemessageidentifierinthelocalmessagestore.Thismessagenameisveryusefulwhenaccessingthemessagecontentlateronduringthetestcase.Thelocalmessagestoreishandledpertestcaseandcontainsallexchangedmessages.Thesampleusesbothheaderandpayloadasmessagepartstosend.Inbothpartsyoucanusevariabledefinitions(see$textand$messageId).Sofirstofallletusrecapwhatvariablesdo.Testvariablesaredefinedattheverybeginningofthetestcaseandarevalidthroughoutallactionsthattakeplaceinthetest.Thismeansthatactionscansimplyreferenceavariablebytheexpression$variable-name.
TipUsevariableswhereveryoucan!Atleasttheimportantentitiesofatestshouldbedefinedasvariablesatthebeginning.Thetestcaseimprovesmaintainabilityandflexibilitywhenusingvariables.
Nowletshaveacloserlookatthesendingaction.The'endpoint'attributemightcatchyourattentionfirst.ThisattributereferencesamessageendpointinCitrusconfigurationbyname.Aspreviouslymentionedthemessageendpointdefinitionlivesinaseparateconfigurationfileandcontainstheactualmessagetransportsettings.Inthisexamplethe"helloServiceEndpoint"isreferencedwhichisamessageendpointforsendingoutmessagesviaJMSorHTTPforinstance.
Thetestcaseisnotawareofanytransportdetails,becauseitdoesnothaveto.Theadvantagesareobvious:Ontheonehandmultipletestcasescanreferencethemessageendpointdefinitionforbetterreuse.Secondlytestcasesareindependentofmessagetransportdetails.Soconnectionfactories,usercredentials,endpointurivaluesandsoonarenotpresentinthetestcase.
CitrusReferenceGuide
116Send
![Page 117: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/117.jpg)
Inotherwordsthe"endpoint"attributeofthe<send>elementspecifieswhichmessageendpointdefinitiontouseandthereforewherethemessageshouldgoto.OnceagainallavailablemessageendpointsareconfiguredinaseparateCitrusconfigurationfile.Wewillcometothislateron.Besuretoalwayspicktherightmessageendpointtypeinordertopublishyourmessagetotherightdestination.
IfyoudonotliketheXMLlanguageyoucanalsousepureJavacodetodefinethesametest.InJavayouwouldalsomakeuseofthemessageendpointdefinitionandreferencethisinstance.ThesametestasshownaboveinJavaDSLlookslikethis:
JavaDSLdesigner
importorg.testng.ITestContext;importorg.testng.annotations.Test;importcom.consol.citrus.annotations.CitrusTest;importcom.consol.citrus.dsl.testng.TestNGCitrusTestDesigner;
@TestpublicclassSendMessageTestDesignerextendsTestNGCitrusTestDesigner
@CitrusTest(name="SendMessageTest")publicvoidsendMessageTest()description("Basicsendmessageexample");
variable("text","HelloCitrus!");variable("messageId","Mx1x123456789");
send("helloServiceEndpoint").name("helloMessage").payload("<TestMessage>"+"<Text>$text</Text>"+"</TestMessage>").header("Operation","sayHello").header("RequestTag","$messageId");
JavaDSLrunner
importorg.testng.ITestContext;importorg.testng.annotations.Test;importcom.consol.citrus.annotations.CitrusTest;importcom.consol.citrus.dsl.testng.TestNGCitrusTestRunner;
@TestpublicclassSendMessageTestRunnerextendsTestNGCitrusTestRunner
CitrusReferenceGuide
117Send
![Page 118: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/118.jpg)
@CitrusTest(name="SendMessageTest")publicvoidsendMessageTest()variable("text","HelloCitrus!");variable("messageId","Mx1x123456789");
send(action->action.endpoint("helloServiceEndpoint").name("helloMessage").payload("<TestMessage>"+"<Text>$text</Text>"+"</TestMessage>").header("Operation","sayHello").header("RequestTag","$messageId"));
InsteadofusingtheXMLtagsforsendweusemethodsfromTestNGCitrusTestDesignerclass.Thesamemessageendpointisreferencedwithinthesendmessageaction.
Nowthatthemessagesenderpatternisclearwecanconcentrateonhowtospecifythemessagecontenttobesent.ThereareseveralpossibilitiesforyoutodefinemessagecontentinCitrus:
message:Thiselementconstructsthemessagetobesent.Thereareseveralchildelementsavailable:payload:NestedXMLpayloadasdirectchildnode.data:InlineCDATAdefinitionofthemessagepayloadresource:ExternalfileresourceholdingthemessagepayloadThesyntaxwouldbe:<resourcefile="classpath:com/consol/citrus/messages/TestRequest.xml"/>Thefilepathprefixindicatestheresourcetype,sothefilelocationisresolvedeitherasfilesystemresource(file:)orclasspathresource(classpath:).element:ExplicitlyoverwritevaluesintheXMLmessagepayloadusingXPath.Youcanreplacemessagecontentwithdynamicvaluesbeforesending.Eachentryprovidesa"path"and"value"attribute.The"path"givesaXPathexpressionevaluatingtoaXMLnodeelementorattributeinthemessage.The"value"canbeavariableexpressionoranyotherstaticvalue.Citruswillreplacethevaluebeforesendingthemessage.header:Definesaheaderforthemessage(e.g.JMSheaderinformationorSOAPheader):element:Eachheaderreceivesa"name"and"value".The"name"willbethenameoftheheaderentryand"value"itsrespectivevalue.Againtheusageofvariableexpressionsasvalueissupportedhere,too.
CitrusReferenceGuide
118Send
![Page 119: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/119.jpg)
XMLDSL
<sendendpoint="helloServiceEndpoint"><message><payload><!--messagepayloadasXML--></payload></message></send>
<sendendpoint="helloServiceEndpoint"><message><data><![CDATA[<!--messagepayloadasXML-->]]></data></message></send>
<sendendpoint="helloServiceEndpoint"><message><resourcefile="classpath:com/consol/citrus/messages/TestRequest.xml"/></message></send>
Themostimportantthingwhendealingwithsendingactionsistopreparethemessagepayloadandheader.YouareabletoconstructthemessagepayloadeitherbynestedXMLchildnodes(payload),asinlineCDATA()orexternalfile().
NoteSometimesthenestedXMLmessagepayloadelementsmaycauseXSDschemavalidationruleviolations.ThisisbecauseofvariablevaluesnotfittingtheXSDschemarulesforexample.InthisscenarioyoucouldalsousesimpleCDATAsectionsaspayloaddata.Inthiscaseyouneedtousethe<data>elementincontrasttothe<payload>elementthatwehaveusedinourexamplessofar.
WiththisalternativeyoucanskiptheXMLschemavalidationfromyourIDEatdesigntime.UnfortunatelyyouwillloosetheXSDautocompletionfeaturesmanyXMLeditorsofferwhenconstructingyourpayload.
TheThesamepossibilitiesapplytotheCitrusJavaDSL.
JavaDSLdesigner
CitrusReferenceGuide
119Send
![Page 120: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/120.jpg)
@CitrusTestpublicvoidmessagingTest()send("helloServiceEndpoint").payload("<TestMessage>"+"<Text>Hello!</Text>"+"</TestMessage>");
@CitrusTestpublicvoidmessagingTest()send("helloServiceEndpoint").payload(newClassPathResource("com/consol/citrus/messages/TestRequest.xml"));
@CitrusTestpublicvoidmessagingTest()send("helloServiceEndpoint").payloadModel(newTestRequest("HelloCitrus!"));
@CitrusTestpublicvoidmessagingTest()send("helloServiceEndpoint").message(newDefaultMessage("HelloWorld!")));
BesidesdefiningmessagepayloadsasnormalStringsandviaexternalfileresource(classpathandfilesystem)youcanalsousemodelobjectsaspayloaddatainJavaDSL.ThismodelobjectpayloadrequiresapropermessagemarshallerthatshouldbeavailableasSpringbeaninsidetheapplicationcontext.BydefaultCitrusissearchingforabeanoftypeorg.springframework.oxm.Marshaller.
IncaseyouhavemultiplemessagemarshallersintheapplicationcontextyouhavetotellCitruswhichonetouseinthisparticularsendmessageaction.
@CitrusTestpublicvoidmessagingTest()send("helloServiceEndpoint").payloadModel(newTestRequest("HelloCitrus!"),"myMessageMarshallerBean");
CitrusReferenceGuide
120Send
![Page 121: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/121.jpg)
NowCitruswillmarshalthemessagepayloadwiththemessagemarshallerbeannamedmyMessageMarshallerBean.Thiswayyoucanhavemultiplemessagemarshallerimplementationsactiveinyourproject(XML,JSON,andsoon).
LastnotleastthemessagecanbedefinedasCitrusmessageobject.HereyoucanchooseoneofthedifferentmessageimplementationsusedinCitrusforSOAP,HttporJMSmessages.Oryoujustusethedefaultmessageimplementationormaybeacustomimplementation.
Beforesendingtakesplaceyoucanexplicitlyoverwritesomemessagevaluesinpayload.Youcanthinkofoverwritingspecificmessageelementswithvariablevalues.AlsoyoucanoverwritevaluesusingXPath(xpath)orJSONPath(json-path)expressions.
Themessageheaderispartofourdutyofdefiningpropermessages,too.SoCitrususesname-valuepairslike"Operation"and"MessageId"inthenextexampletosetmessageheaderentries.Dependingonwhatmessageendpointisusedandwhichmessagetransportunderneaththeheadervalueswillbeshippedindifferentways.InJMStheheadersgototheheadersectionofthemessage,inHttpwesetmimeheadersaccordingly,inSOAPwecanaccesstheSOAPheaderelementsandsoon.Citrusaimstodothehardworkforyou.SoCitrusknowshowtosetheadersondifferentmessagetransports.
XMLDSL
<sendendpoint="helloServiceEndpoint"><message><payload><TestMessage><Text>Hello!</Text></TestMessage></payload></message><header><elementname="Operation"value="sayHello"/></header></receive>
Themessageheaderstosendaredefinedbyasimplenameandvaluepair.Ofcourseyoucanusetestvariablesinheadervaluesaswell.Let'sseehowthislookslikeinJavaDSL:
JavaDSLdesigner
CitrusReferenceGuide
121Send
![Page 122: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/122.jpg)
@CitrusTestpublicvoidmessagingTest()receive("helloServiceEndpoint").payload("<TestMessage>"+"<Text>Hello!</Text>"+"</TestMessage>").header("Operation","sayHello");
JavaDSLrunner
@CitrusTestpublicvoidmessagingTest()receive(action->action.endpoint("helloServiceEndpoint").payload("<TestMessage>"+"<Text>Hello!</Text>"+"</TestMessage>").header("Operation","sayHello"));
ThisisbasicallyhowtosendmessagesinCitrus.Thetestcaseisresponsibleforconstructingthemessagecontentwhilethepredefinedmessageendpointholdstransportspecificsettings.Testcasesreferenceendpointcomponentstopublishmessagestotheoutsideworld.Thevariablesupportinmessagepayloadandmessageheaderenablesyoutoadddynamicvaluesbeforesendingoutthemessage.
CitrusReferenceGuide
122Send
![Page 123: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/123.jpg)
Receivingmessages
Justlikesendingmessagesthereceivingpartisaveryimportantactioninanintegrationtest.HonestlythereceiveactionisevenmoreimportantinCitrusaswealsowanttovalidatetheincomingmessagecontents.Wearewritingatestsowealsoneedassertionsandchecksthateverythingworksasexpected.
Asalreadymentionedbeforeamessageconsistsofamessageheader(name-valuepairs)andamessagepayload.Laterinthisdocumentwewillseehowtovalidateincomingmessageswithpayloadandheadervalues.Westartwithaverysimpleexample:
XMLDSL
<receiveendpoint="helloServiceEndpoint"><messagename="helloRequest"><payload><TestMessage><Text>$text</Text></TestMessage></payload></message><header><elementname="Operation"value="sayHello"/><elementname="MessageId"value="$messageId"/></header></receive>
Overallthereceivemessageactionlooksquitesimilartothesendmessageaction.Conceptsareidenticalaswedefinethemessagecontentwithpayloadandheadervalues.Themessagenameisoptionalanddefinesthemessageidentifierinthelocalmessagestore.Thismessagenameisveryusefulwhenaccessingthemessagecontentlateronduringthetestcase.Thelocalmessagestoreishandledpertestcaseandcontainsallexchangedmessages.
Wecanusetestvariablesinbothmessagepayloadanheaders.NowletushavealookattheJavaDSLrepresentationofthissimpleexample:
JavaDSLdesigner
@CitrusTestpublicvoidmessagingTest()receive("helloServiceEndpoint")
CitrusReferenceGuide
123Receive
![Page 124: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/124.jpg)
.name("helloRequest").payload("<TestMessage>"+"<Text>$text</Text>"+"</TestMessage>").header("Operation","sayHello").header("MessageId","$messageId");
JavaDSLrunner
@CitrusTestpublicvoidmessagingTest()receive(action->action.endpoint("helloServiceEndpoint").name("helloRequest").payload("<TestMessage>"+"<Text>$text</Text>"+"</TestMessage>").header("Operation","sayHello").header("MessageId","$messageId"));
Thereceiveactionwaitsforamessagetoarrive.Thewholetestexecutionisstoppedwhilewaitingforthemessage.Thisisimportanttoensurethestepbysteptestworkflowprocessing.Ofcourseyoucanspecifymessagetimeoutssothereceiverwillonlywaitagivenamountoftimebeforeraisingatimeouterror.Followingfromthattimeoutexceptionthetestcasefailsasthemessagedidnotarriveintime.Citrusdefinesdefaulttimeoutsettingsforallmessagereceivingtasks.
Inagoodcasescenariothemessagearrivesintimeandthecontentcanbevalidatedasanextstep.Thisvalidationcanbedoneinvariousways.OntheonehandyoucanspecifyawholeXMLmessagethatyouexpectascontroltemplate.Inthiscasethereceivedmessagestructureiscomparedtotheexpectedmessagecontentelementbyelement.Ontheotherhandyoucanuseexplicitelementvalidationwhereonlyasmallsubsetofmessageelementsisincludedintovalidation.
BesidesthemessagepayloadCitruswillalsoperformvalidationonthereceivedmessageheadervalues.Testvariableusageissupportedasusualduringthewholevalidationprocessforpayloadandheaderchecks.
Ingeneralthevalidationcomponent(validator)inCitrusworkshandinhandwithamessagereceivingcomponentasthefollowingfigureshows:
CitrusReferenceGuide
124Receive
![Page 125: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/125.jpg)
Themessagereceivingcomponentpassesthemessagetothevalidatorwheretheindividualvalidationstepsareperformed.Letushaveacloserlookatthevalidationoptionsandfeaturesstepbystep.
Validatemessagepayloads
Themostdetailedvalidationofincomingmessagesistodefinesomeexpectedmessagepayload.TheCitrusmessagevalidatorwillthenperformadetailedmessagepayloadcomparison.Theincomingmessagehastomatchexactlytotheexpectedmessagepayload.ThedifferentmessagevalidatorimplementationsinCitrusprovidedeepcomparisonofmessagestructuressuchasXML,JSONandsoon.
Sobydefininganexpectedmessagepayloadwevalidatetheincomingmessageinsyntaxandsemantics.Incaseadifferenceisidentifiedbythemessagevalidatorthevalidationandthetestcasefailswithrespectiveexceptions.Thisishowyoucandefinemessagepayloadsinreceiveaction:
XMLDSL
<receiveendpoint="helloServiceEndpoint"><message><payload><!--messagepayloadasXML--></payload></message></receive>
<receiveendpoint="helloServiceEndpoint"><message><data><![CDATA[<!--messagepayloadasXML-->]]></data></message></receive>
<receiveendpoint="helloServiceEndpoint"><message>
CitrusReferenceGuide
125Receive
![Page 126: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/126.jpg)
<resourcefile="classpath:com/consol/citrus/messages/TestRequest.xml"/></message></receive>
Thethreeexamplesaboverepresentthreedifferentwaysofdefiningthemessagepayloadinareceivemessageaction.OntheonehandwecanuseinlinemessagepayloadsasnestedXMLorCDATAsectionsinthetest.Ontheotherhandwecanloadthemessagecontentfromexternalfileresource.
NoteSometimesthenestedXMLmessagepayloadelementsmaycauseXSDschemavalidationruleviolations.ThisisbecauseofvariablevaluesnotfittingtheXSDschemarulesforexample.InthisscenarioyoucouldalsousesimpleCDATAsectionsaspayloaddata.Inthiscaseyouneedtousethe<data>elementincontrasttothe<payload>elementthatwehaveusedinourexamplessofar.
WiththisalternativeyoucanskiptheXMLschemavalidationfromyourIDEatdesigntime.UnfortunatelyyouwillloosetheXSDautocompletionfeaturesmanyXMLeditorsofferwhenconstructingyourpayload.
InJavaDSLwealsohavemultipleoptionsforspecifyingthemessagepayloads:
JavaDSLdesigner
@CitrusTestpublicvoidmessagingTest()receive("helloServiceEndpoint").payload("<TestMessage>"+"<Text>Hello!</Text>"+"</TestMessage>");
@CitrusTestpublicvoidmessagingTest()receive("helloServiceEndpoint").payload(newClassPathResource("com/consol/citrus/messages/TestRequest.xml"));
@CitrusTestpublicvoidmessagingTest()receive("helloServiceEndpoint").payloadModel(newTestRequest("HelloCitrus!"));
CitrusReferenceGuide
126Receive
![Page 127: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/127.jpg)
@CitrusTestpublicvoidmessagingTest()receive("helloServiceEndpoint").message(newDefaultMessage("HelloWorld!")));
TheexamplesaboverepresentthebasicvariationsofhowtodefinemessagepayloadsinCitrusJavaDSL.ThepayloadcanbeasimpleStringoraSpringfileresource(classpathorfilesystem).Inadditiontothatwecanuseamodelobject.WhenusingmodelobjectsaspayloadsweneedapropermessagemarshallerimplementationintheSpringapplicationcontext.Bydefaultthisisamarshallerbeanoftypeorg.springframework.oxm.MarshallerthathastobepresentintheSpringapplicationcontext.YoucanaddsuchabeanforXMLandJSONmessagemarshallingforinstance.
IncaseyouhavemultiplemessagemarshallersintheapplicationcontextyouhavetotellCitruswhichonetouseinthisparticularsendmessageaction.
@CitrusTestpublicvoidmessagingTest()receive("helloServiceEndpoint").payloadModel(newTestRequest("HelloCitrus!"),"myMessageMarshallerBean");
NowCitruswillmarshalthemessagepayloadwiththemessagemarshallerbeannamedmyMessageMarshallerBean.Thiswayyoucanhavemultiplemessagemarshallerimplementationsactiveinyourproject(XML,JSON,andsoon).
LastnotleastthemessagecanbedefinedasCitrusmessageobject.HereyoucanchooseoneofthedifferentmessageimplementationsusedinCitrusforSOAP,HttporJMSmessages.Oryoujustusethedefaultmessageimplementationormaybeacustomimplementation.
IngeneraltheexpectedmessagecontentcanbemanipulatedusingXPath(xpath)orJSONPath(json-path).Inadditiontothatyoucanignoresomeelementsthatareskippedincomparison.Wewilldescribethislateroninthissection.Nowletscontinuewithmessageheadervalidation.
Validatemessageheaders
CitrusReferenceGuide
127Receive
![Page 128: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/128.jpg)
Messageheadersareusedwidelyinenterprisemessagingsolution:Themessageheadersarepartofthemessagesemanticsandneedtobevalidated,too.Citruscanvalidatemessageheaderbynameandvalue.
XMLDSL
<receiveendpoint="helloServiceEndpoint"><message><payload><TestMessage><Text>Hello!</Text></TestMessage></payload></message><header><elementname="Operation"value="sayHello"/></header></receive>
Theexpectedmessageheadersaredefinedbyanameandvaluepair.Citruswillcheckthattheexpectedmessageheaderispresentandwillcheckthevalue.IncasethemessageheaderisnotfoundorthevaluedoesnotmatchCitruswillraiseanexceptionandthetestfails.Youcanusevalidationmatchers(validation-matchers)foramorepowerfulvalidationofheadervalues,too.
Let'sseehowthislookslikeinJavaDSL:
JavaDSLdesigner
@CitrusTestpublicvoidmessagingTest()receive("helloServiceEndpoint").payload("<TestMessage>"+"<Text>Hello!</Text>"+"</TestMessage>").header("Operation","sayHello");
JavaDSLrunner
@CitrusTestpublicvoidmessagingTest()receive(action->action.endpoint("helloServiceEndpoint").payload("<TestMessage>"+"<Text>Hello!</Text>"+"</TestMessage>")
CitrusReferenceGuide
128Receive
![Page 129: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/129.jpg)
.header("Operation","sayHello"));
HeaderdefinitioninJavaDSLisstraightforwardaswejustdefinenameandvalueasusual.ThiscompletesthemessagevalidationwhenreceivingamessageinCitrus.ThemessagevalidatorimplementationsmayaddadditionalvalidationcapabilitiessuchasXMLschemavalidationorXPathandJSONPathvalidation.Pleaserefertotherespectivechaptersinthisguidetolearnmoreaboutthat.
Messageselectors
The<selector>elementinsidethereceivingactiondefineskey-valuepairsinordertofilterthemessagesbeingreceived.Thefilterappliestothemessageheaders.Thismeansthatareceiverwillonlyacceptmessagesmatchingaheaderelementvalue.Inmessagingapplicationstheheaderinformationoftenholdsmessageids,correlationids,operationnamesandsoon.Withthisinformationgivenyoucanexplicitlylistenformessagesthatbelongtoyourtestcase.Thisisveryhelpfultoavoidreceivingmessagesthatarestillavailableonthemessagedestination.
Letssaythetestedsoftwareapplicationkeepssendingmessagesthatbelongtoprevioustestcases.Thiscouldhappeninretrysituationswheretheapplicationerrorhandlingautomaticallytriestosolveacommunicationproblemthatoccurredduringprevioustestcases.Asaresultamessagedestination(e.g.aJMSmessagequeue)containsmessagesthatarenotvalidanymoreforthecurrentlyrunningtestcase.Thetestcasemightfailbecausethereceivedmessagedoesnotapplytotheactualusecase.Sowewilldefinitelyrunintovalidationerrorsastheexpectedmessagecontrolvaluesdonotmatch.
Nowwehavetofindawaytoavoidtheseproblems.Thetestcouldfilterthemessagesonadestinationtoonlyreceivemessagesthatapplyfortheusecasethatisbeingtested.TheJavaMessagingSystem(JMS)cameupwithamessageheaderselectorthatwillonlyacceptmessagesthatfittheexpectedheadervalues.
Letushaveacloserlookatamessageselectorinsideareceivingaction:
XMLDSL
<selector><element>name="correlationId"value="Cx1x123456789"</element><element>name="operation"value="getOrders"</element></selector>
CitrusReferenceGuide
129Receive
![Page 130: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/130.jpg)
JavaDSLdesigner
@CitrusTestpublicvoidreceiveMessageTest()receive("testServiceEndpoint").selector("correlationId='Cx1x123456789'ANDoperation='getOrders'");
JavaDSLrunner
@CitrusTestpublicvoidreceiveMessageTest()receive(action->action.endpoint("testServiceEndpoint").selector("correlationId='Cx1x123456789'ANDoperation='getOrders'"));
Thisexampleshowshowmessageselectorswork.Theselectorwillonlyacceptmessagesthatmeetthecorrelationidandtheoperationintheheadervalues.Allothermessagesonthemessagedestinationareignored.TheselectorelementsareautomaticallyassociatedtoeachotherusingthelogicalANDoperator.Thismeansthatthemessageselectorstringwouldlooklikethis:correlationId='Cx1x123456789'ANDoperation='getOrders'.
Insteadofusingseveralelementsintheselectoryoucanalsodefineaselectorstringdirectlywhichgivesyoumorepowerinconstructingtheselectionlogicyourself.ThiswayyoucanuseANDlogicaloperatorsyourself.
<selector><value>correlationId='Cx1x123456789'ANDoperation='getOrders'</value></selector>
ImportantIncaseyouwanttoruntestsinparallelmessageselectorsbecomeessentialinyourtestcases.Thedifferenttestsrunningatthesametimewillstealmessagesfromeachotherwhenyoulackofmessageselectionmechanisms.
ImportantPreviouslyonlyJMSmessagedestinationsofferedsupportformessageselectors!WithCitrusversion1.2weintroducedmessageselectorsupportforSpringIntegrationmessagechannels,too(seemessage-channel-selector-support).
GroovyMarkupBuilder
CitrusReferenceGuide
130Receive
![Page 131: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/131.jpg)
WiththeGroovyMarkupBuilderyoucanbuildXMLmessagepayloadsinasimpleway,withouthavingtowritethetypicalXMLoverhead.ForexampleweuseaGroovyscripttoconstructtheXMLmessagetobesentout.InsteadofaplainCDATAXMLsectionorthenestedpayloadXMLdatawewriteaGroovyscriptsnippet.TheGroovyMarkupBuildergeneratestheXMLmessagepayloadwithexactlythesameresult:
XMLDSL
<sendendpoint="helloServiceEndpoint"><message><buildertype="groovy">markupBuilder.TestMessageMessageId('$messageId')Timestamp('?')VersionId('2')Text('HelloCitrus!')</builder><elementpath="/TestMessage/Timestamp"value="$createDate"/></message><header><elementname="Operation"value="sayHello"/><elementname="MessageId"value="$messageId"/></header></send>
WeusethebuilderelementwithtypegroovyandtheMarkupBuildercodeisdirectlywrittentothiselement.Asyoucanseefromtheexampleabove,youcanmixXPathandGroovymarkupbuildercode.TheMarkupBuildersyntaxisveryeasyandfollowsthesimplerule:markupBuilder.ROOT-ELEMENTCHILD-ELEMENTS.HoweverthetesterhastofollowsomesimplerulesandnamingconventionswhenusingtheCitrusMarkupBuilderextension:
TheMarkupBuilderisaccessedwithinthescriptoveranobjectnamedmarkupBuilder.Thenameofthecustomrootelementfollowswithallitschildelements.Childelementsmaybedefinedwithincurlybracketsaftertheroot-element(thesameappliesforfurthernestedchildelements)Attributesandelementvaluesaredefinedwithinroundbrackets,aftertheelementnameAttributeandelementvalueshavetostandwithinapostrophes(e.g.attribute-name:'attribute-value')
CitrusReferenceGuide
131Receive
![Page 132: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/132.jpg)
TheGroovyMarkupBuilderscriptmayalsobeusedwithinreceiveactionsasshowninthefollowinglisting:
XMLDSL
<sendendpoint="helloServiceEndpoint"><message><buildertype="groovy"file="classpath:com/consol/citrus/groovy/helloRequest.groovy"/></message></send>
<receiveendpoint="helloServiceEndpoint"timeout="5000"><message><buildertype="groovy">markupBuilder.TestResponse(xmlns:'http://www.consol.de/schemas/samples/sayHello.xsd')MessageId('$messageId')CorrelationId('$correlationId')User('HelloService')Text('Hello$user')</builder></message></receive>
Asyoucanseeitisalsopossibletodefinethescriptasexternalfileresource.Inadditiontothatnamespacesupportisgivenasnormalattributedefinitionwithintheroundbracketsaftertheelementname.
TheMarkupBuilderimplementationinGroovyoffersgreatpossibilitiesindefiningmessagepayloads.WedonotneedtowriteXMLtagoverheadandwecanconstructcomplexmessagepayloadswithGroovylogiclikeiterationsandconditionalelements.FordetailedMarkupBuilderdescriptionspleaseseetheofficialGroovydocumentation.
CitrusReferenceGuide
132Receive
![Page 133: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/133.jpg)
Databaseactions
Inmanycasesitisnecessarytoaccessthedatabaseduringatest.Thisenablesatestertoalsovalidatethepersistentdatainadatabase.Itmightalsobehelpfultopreparethedatabasewithsometestdatabeforerunningatest.Youcandothisusingthetwodatabaseactionsthataredescribedinthefollowingsections.
IngeneralCitrushandlesSELECTstatementsdifferentlytootherstatementslikeINSERT,UPDATEandDELETE.WhenexecutingaSQLquerywithSELECTyouareabletoaddvalidationstepsontheresultsetsreturnedfromthedatabase.ThisisnotallowedwhenexecutingupdatestatementslikeINSERT,UPDATE,DELETE.
ImportantDonotmixstatementsoftypeSELECTwithothersinasinglesqltestaction.ThiswillleadtoerrorsbecausevalidationstepsarenotvalidforstatementsotherthanSELECT.Pleaseuseseparatetestactionsforupdatestatements.
SQLupdate,insert,delete
TheactionsimplyexecutesagroupofSQLstatementsinordertochangedatainadatabase.Typicallytheactionisusedtopreparethedatabaseatthebeginningofatestortocleanupthedatabaseattheendofatest.YoucanspecifySQLstatementslikeINSERT,UPDATE,DELETE,CREATETABLE,ALTERTABLEandmanymore.
OntheonehandyoucanspecifythestatementsasinlineSQLorstoredinanexternalSQLresourcefileasshowninthenexttwoexamples.
XMLDSL
<actions><sqldatasource="someDataSource"><statement>DELETEFROMCUSTOMERS</statement><statement>DELETEFROMORDERS</statement></sql>
<sqldatasource="myDataSource"><resourcefile="file:tests/unit/resources/script.sql"/></sql></actions>
JavaDSLdesigner
@Autowired
CitrusReferenceGuide
133Database
![Page 134: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/134.jpg)
@Qualifier("myDataSource")privateDataSourcedataSource;
@CitrusTestpublicvoidsqlTest()sql(dataSource).statement("DELETEFROMCUSTOMERS").statement("DELETEFROMORDERS");
sql(dataSource).sqlResource("file:tests/unit/resources/script.sql");
JavaDSLrunner
@Autowired@Qualifier("myDataSource")privateDataSourcedataSource;
@CitrusTestpublicvoidsqlTest()sql(action->action.dataSource(dataSource).statement("DELETEFROMCUSTOMERS").statement("DELETEFROMORDERS"));
sql(action->action.dataSource(dataSource).sqlResource("file:tests/unit/resources/script.sql"));
ThefirstactionusesinlineSQLstatementsdefineddirectlyinsidethetestcase.ThenextactionusesanexternalSQLresourcefileinstead.ThefileresourcecanholdseveralSQLstatementsseparatedbynewlines.Allstatementsinsidethefileareexecutedsequentiallybytheframework.
ImportantYouhavetopayattentiontosomeruleswhendealingwithexternalSQLresources.
EachstatementshouldbegininanewlineItisnotallowedtodefinestatementswithwordwrappingCommentsbeginwithtwodashes"--"
NoteTheexternalfileisreferencedeitherasfilesystemresourceorclasspathresource,byusingthe"file:"or"classpath:"prefix.
CitrusReferenceGuide
134Database
![Page 135: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/135.jpg)
Bothexamplesusethe"datasource"attribute.Thisvaluedefinesthedatabasedatasourcetobeused.Theconnectiontoadatasourceismandatory,becausethetestcasedoesnotknowaboutusercredentialsordatabasenames.The'datasource'attributereferencespredefineddatasourcesthatarelocatedinaseparateSpringconfigurationfile.
SQLquery
ThequeryactionisspeciallydesignedtoexecuteSQLqueries(SELECT*FROM).Sothetestisabletoreaddatafromadatabase.Thequeryresultsarevalidatedagainstexpecteddataasshowninthenextexample.
XMLDSL
<sqldatasource="testDataSource"><statement>selectNAMEfromCUSTOMERSwhereID='$customerId'</statement><statement>selectcount(*)fromERRORS</statement><statement>selectIDfromORDERSwhereDESCLIKE'Def%'</statement><statement>selectDESCRIPTIONfromORDERSwhereID='$id'</statement>
<validatecolumn="ID"value="1"/><validatecolumn="NAME"value="Christoph"/><validatecolumn="COUNT(*)"value="$rowsCount"/><validatecolumn="DESCRIPTION"value="null"/></sql>
JavaDSLdesigner
@Autowired@Qualifier("testDataSource")privateDataSourcedataSource;
@CitrusTestpublicvoiddatabaseQueryTest()query(dataSource).statement("selectNAMEfromCUSTOMERSwhereCUSTOMER_ID='$customerId'").statement("selectCOUNT(1)asoverall_cntfromERRORS").statement("selectORDER_IDfromORDERSwhereDESCRIPTIONLIKE'Migrate%'").statement("selectDESCRIPTIONfromORDERSwhereORDER_ID=2").validate("ORDER_ID","1").validate("NAME","Christoph").validate("OVERALL_CNT","$rowsCount").validate("DESCRIPTION","NULL");
CitrusReferenceGuide
135Database
![Page 136: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/136.jpg)
JavaDSLrunner
@Autowired@Qualifier("testDataSource")privateDataSourcedataSource;
@CitrusTestpublicvoiddatabaseQueryTest()query(action->action.dataSource(dataSource).statement("selectNAMEfromCUSTOMERSwhereCUSTOMER_ID='$customerId'").statement("selectCOUNT(1)asoverall_cntfromERRORS").statement("selectORDER_IDfromORDERSwhereDESCRIPTIONLIKE'Migrate%'").statement("selectDESCRIPTIONfromORDERSwhereORDER_ID=2").validate("ORDER_ID","1").validate("NAME","Christoph").validate("OVERALL_CNT","$rowsCount").validate("DESCRIPTION","NULL"));
Theactionoffersawiderangeofvalidatingfunctionalityfordatabaseresultsets.FirstofallyouhavetoselectthedataviaSQLstatements.HereagainyouhavethechoicetouseinlineSQLstatementsorexternalfileresourcepattern.
Theresultsetsarevalidatedthroughelements.Itispossibletodoadetailedcheckoneveryselectedcolumnoftheresultset.Simplyrefertotheselectedcolumnnameinordertovalidateitsvalue.Theusageoftestvariablesissupportedaswellasdatabaseexpressionslikecount(),avg(),min(),max().
Yousimplydefinetheentrywiththecolumnnameasthe"column"attributeandanyexpectedvalueexpressionasexpected"value".Theframeworkthenwillcheckthecolumntofittheexpectedvalueandraisevalidationerrorsincaseofmismatch.
LookingatthefirstSELECTstatementintheexampleyouwillseethattestvariablesaresupportedintheSQLstatements.Theframeworkwillreplacethevariablewithitsrespectivevaluebeforesendingittothedatabase.
Inthevalidationsectionvariablescanbeusedtoo.Lookatthethirdvalidationentry,wherethevariable"$rowsCount"isused.Thelastvalidationinthisexampleshows,thatNULLvaluesarealsosupportedasexpectedvalues.
Ifasinglevalidationhappenstofail,thewholeactionwillfailwithrespectivevalidationerrors.
CitrusReferenceGuide
136Database
![Page 137: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/137.jpg)
ImportantThevalidationwith""meetssinglerowresultsetsasyouspecifyasinglecolumncontrolvalue.Incaseyouhavemultiplerowsinaresultsetyouratherneedtovalidatethecolumnswithmultiplecontrolvalueslikethis:
<validatecolumn="someColumnName"><values><value>Valuein1strow</value><value>Valuein2ndrow</value><value>Valuein3rdrow</value><value>Valueinxrow</value></values></validate>
WithinJavayoucanpassavariableargumentlisttothevalidatemethodlikethis:
query(dataSource).statement("selectNAMEfromWEEKDAYSwhereNAMELIKE'S%'").validate("NAME","Saturday","Sunday")
Nextexampleshowshowtoworkwithmultiplerowresultsetsandmultiplevaluestoexpectwithinonecolumn:
<sqldatasource="testDataSource"><statement>selectWEEKDAYasDAY,DESCRIPTIONfromWEEK</statement><validatecolumn="DAY"><values><value>Monday</value><value>Tuesday</value><value>Wednesday</value><value>Thursday</value><value>Friday</value><value>@ignore@</value><value>@ignore@</value></values></validate><validatecolumn="DESCRIPTION"><values><value>IhateMondays!</value><value>Tuesdayissportsday</value><value>Themidoftheweek</value><value>Thursdayweplaychess</value><value>Friday,theweekendisnear!</value><value>@ignore@</value><value>@ignore@</value></values>
CitrusReferenceGuide
137Database
![Page 138: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/138.jpg)
</validate></sql>
Forthevalidationofmultiplerowsthe<validate>elementisabletohostalistofcontrolvaluesforacolumn.Asyoucanseefromtheexampleabove,youhavetoaddacontrolvalueforeachrowintheresultset.Thisalsomeansthatwehavetotakecareofthetotalnumberofrows.Fortunatelywecanusetheignoreplaceholder,inordertoskipthevalidationofaspecificrowintheresultset.Functionsandvariablesaresupportedasusual.
ImportantItisimportant,thatthecontrolvaluesaredefinedinthecorrectorder,becausetheyarecomparedoneononewiththeactualresultsetcomingfromdatabasequery.Youmayneedtoadd"orderby"SQLexpressionstogettherightorderofrowsreturned.Ifanyofthevaluesfailsinvalidationorthetotalnumberofrowsisnotequal,thewholeactionwillfailwithrespectivevalidationerrors.
GroovySQLresultsetvalidation
GroovyprovidesgreatsupportforaccessingJavalistobjectsandmaps.AsaJavaSQLresultsetisnothingbutalistofmaprepresentations,whereeachentryinthelistdefinesarowintheresultsetandeachmapentryrepresentsthecolumnsandvalues.SowithGroovy'slistandmapaccesswehavegreatpossibilitiestovalidateaSQLresultset-outofthebox.
XMLDSL
<sqldatasource="testDataSource"><statement>selectIDfromCUSTOMERSwhereNAME='$customerName'</statement><statement>selectORDERTYPE,STATUSfromORDERSwhereID='$orderId'</statement>
<validate-scripttype="groovy">assertrows.size()==2assertrows[0].ID=='1'assertrows[1].STATUS=='inprogress'assertrows[1]==[ORDERTYPE:'SampleOrder',STATUS:'inprogress']</validate-script></sql>
JavaDSLdesigner
query(dataSource).statement("selectORDERTYPE,STATUSfromORDERSwhereID='$orderId'").validateScript("assertrows.size==2;"+
CitrusReferenceGuide
138Database
![Page 139: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/139.jpg)
"assertrows[0].ID=='1';"+"assertrows[0].STATUS=='inprogress';","groovy");
JavaDSLrunner
query(action->action.dataSource(dataSource).statement("selectORDERTYPE,STATUSfromORDERSwhereID='$orderId'").validateScript("assertrows.size==2;"+"assertrows[0].ID=='1';"+"assertrows[0].STATUS=='inprogress';","groovy"));
AsyoucanseeGroovyprovidesfantasticaccessmethodstotheSQLresultset.Wecanbrowsetheresultsetwithnamedcolumnvaluesandcheckthesizeoftheresultset.Wearealsoabletosearchforanentry,iterateovertheresultsetandhaveotherhelpfuloperations.ForadetaileddescriptionofthelistandmaphandlinginGroovymyadviceforyouistohavealookattheofficialGroovydocumentation.
NoteIngeneralotherscriptlanguagesdoalsosupportthiskindoflistandmapaccess.FornowwejusthaveimplementedtheGroovyscriptsupport,buttheframeworkisreadytoworkwithallothergreatscriptlanguagesoutthere,too(e.g.Scala,Clojure,Fantom,etc.).Soifyouprefertoworkwithanotherlanguagejoinandhelpusimplementthosefeatures.
Saveresultsetvalues
Nowthevalidationofdatabaseentriesisaverypowerfulfeaturebutsometimeswesimplydonotknowthepersistedcontentvalues.Thetestmaywanttoreaddatabaseentriesintotestvariableswithoutvalidation.Citrusisabletodothatwiththefollowingexpressions:
XMLDSL
<sqldatasource="testDataSource"><statement>selectIDfromCUSTOMERSwhereNAME='$customerName'</statement><statement>selectSTATUSfromORDERSwhereID='$orderId'</statement>
<extractcolumn="ID"variable="$customerId"/><extractcolumn="STATUS"variable="$orderStatus"/></sql>
JavaDSLdesigner
CitrusReferenceGuide
139Database
![Page 140: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/140.jpg)
query(dataSource).statement("selectSTATUSfromORDERSwhereID='$orderId'").extract("STATUS","orderStatus");
JavaDSLrunner
query(action->action.dataSource(dataSource).statement("selectSTATUSfromORDERSwhereID='$orderId'").extract("STATUS","orderStatus"));
Wecansavethedatabasecolumnvaluesdirectlytotestvariables.Ofcourseyoucancombinethevalueextractionwiththenormalcolumnvalidationdescribedearlierinthischapter.Pleasekeepinmindthatwecannotusetheseoperationsonresultsetswithmultiplerows.Citruswillalwaysusethefirstrowinaresultset.
CitrusReferenceGuide
140Database
![Page 141: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/141.jpg)
Sleep
Thisactionshowshowtomakethetestframeworksleepforagivenamountoftime.Theattribute'time'definestheamountoftimetowaitinseconds.Asshowninthenextexampledecimalvaluesaresupportedtoo.Whennowaitingtimeisspecifiedthedefaulttimeof50000millisecondsapplies.
XMLDSL
<testcasename="sleepTest"><actions><sleepseconds="3.5"/>
<sleepmilliseconds="500"/>
<sleep/></actions></testcase>
JavaDSLdesignerandrunner
@CitrusTestpublicvoidsleepTest()sleep(500);//sleep500milliseconds
sleep();//sleepdefaulttime
Whenshouldsomebodyusethisaction?Tousthisactionwasalwaysveryusefulincasethetestneededtowaituntilanapplicationhaddonesomework.Forexampleinsomecasestheapplicationtooksometimetowritesomedataintothedatabase.Wewaitedthenasmallamountoftimeinordertoavoidunnecessarytestfailures,becausethetestframeworksimplyvalidatedthedatabasetooearly.Orasanotherexamplethetestmaywaitagiventimeuntilretrymechanismsaretriggeredinthetestedapplicationandthenproceedwiththetestactions.
CitrusReferenceGuide
141Sleep
![Page 142: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/142.jpg)
Java
ThetestframeworkiswritteninJavaandrunsinsideaJavavirtualmachine.ThefunctionalityofcallingotherJavaobjectsandmethodsinthissameJavaVMthroughJavaReflectionisself-evident.WiththisactionyoucancallanyJavaAPIavailableatruntimethroughthespecifiedJavaclasspath.
Theactionsyntaxlookslikefollows:
<javaclass="com.consol.citrus.test.util.InvocationDummy"><constructor><argumenttype="">TestInvocation</argument></constructor><methodname="invoke"><argumenttype="String[]">1,2</argument></method></java>
<javaclass="com.consol.citrus.test.util.InvocationDummy"><constructor><argumenttype="">TestInvocation</argument></constructor><methodname="invoke"><argumenttype="int">4</argument><argumenttype="String">TestInvocation</argument><argumenttype="boolean">true</argument></method></java>
<javaclass="com.consol.citrus.test.util.InvocationDummy"><methodname="main"><argumenttype="String[]">4,Test,true</argument></method></java>
TheJavaclassisspecifiedbyfullyqualifiedclassname.Constructorargumentsareaddedusingtheelementwithalistofchildelements.Thetypeoftheargumentisdefinedwithintherespectiveattribute"type".BydefaultthetypewouldbeString.
TheinvokedmethodontheJavaobjectissimplyreferencedbyitsname.Methodargumentsdonotbringanythingnewafterknowingtheconstructorargumentdefinition,dothey?.
CitrusReferenceGuide
142Java
![Page 143: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/143.jpg)
Methodargumentssupportdatatypeconversiontoo,evenstringarrays(usefulwhencallingCLIs).Inthethirdactionintheexamplecodeyoucanseethatcolonseparatedstringsareautomaticallyconvertedtostringarrays.
Simpledatatypesaredefinedbytheirname(int,boolean,floatetc.).Besurethattheinvokedmethodandclassconstructorfityourargumentsandviceversa,otherwiseyouwillcauseerrorsatruntime.
BesidesinstantiatingafullynewobjectinstanceforaclasshowaboutreusingabeaninstanceavailableinSpringbeancontainer.SimplyusetherefattributeandrefertoanexistingbeaninSpringapplicationcontext.
<javaref="invocationDummy"><methodname="invoke"><argumenttype="int">4</argument><argumenttype="String">TestInvocation</argument><argumenttype="boolean">true</argument></method></java>
<beanid="invocationDummy"class="com.consol.citrus.test.util.InvocationDummy"/>
ThemethodisinvokedontheSpringbeaninstance.Thisisveryusefulasyoucaninjectotherobjects(e.g.viaAutowiring)totheSpringbeaninstancebeforemethodinvocationintesttakesplace.ThisenablesyoutoexecuteanyJavalogicinsideatestcase.
CitrusReferenceGuide
143Java
![Page 144: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/144.jpg)
Receivetimeout
Insomecasesitmightbenecessarytovalidatethatamessageisnotpresentonadestination.Thismeansthatthisactionexpectsatimeoutwhenreceivingamessagefromanendpointdestination.Forinstancethetesterintendstoensurethatnomessageissenttoacertaindestinationinatimeperiod.Inthatcasethetimeoutwouldnotbeatestabortingerrorbuttheexpectedbehavior.Andincontrasttothenormalbehaviorwhenamessageisreceivedinthetimeperiodthetestwillfailwitherror.
Inordertovalidatesuchatimeoutsituationtheactionshallhelp.Theusageisverysimpleasthefollowingexampleshows:
XMLDSL
<testcasename="receiveJMSTimeoutTest"><actions><expect-timeoutendpoint="myEndpoint"wait="500"/></actions></testcase>
JavaDSLdesigner
@Autowired@Qualifier("myEndpoint")privateEndpointmyEndpoint;
@CitrusTestpublicvoidreceiveTimeoutTest()receiveTimeout(myEndpoint).timeout(500);
JavaDSLrunner
@Autowired@Qualifier("myEndpoint")privateEndpointmyEndpoint;
@CitrusTestpublicvoidreceiveTimeoutTest()receiveTimeout(action->action.endpoint(myEndpoint).timeout(500));
CitrusReferenceGuide
144Timeout
![Page 145: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/145.jpg)
Theactionofferstwoattributes:
endpoint:Referencetoamessageendpointthatwilltrytoreceivemessages.
wait/timeout:Timeperiodtowaitformessagestoarrive
Sometimesyoumaywanttoaddsomeselectoronthetimeoutreceivingaction.Thiswayyoucanveryselectivecheckonamessagetonotbepresentonamessagedestination.Thisispossiblewithdefiningamessageselectoronthetestactionasfollows.
XMLDSL
<expect-timeoutendpoint="myEndpoint"wait="500"><select>MessageId='123456789'<select/><expect-timeout/>
JavaDSLdesigner
@CitrusTestpublicvoidreceiveTimeoutTest()receiveTimeout(myEndpoint).selector("MessageId='123456789'").timeout(500);
JavaDSLrunner
@CitrusTestpublicvoidreceiveTimeoutTest()receiveTimeout(action->action.endpoint(myEndpoint).selector("MessageId='123456789'").timeout(500));
CitrusReferenceGuide
145Timeout
![Page 146: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/146.jpg)
Echo
Theactionprintsmessagestotheconsole/logger.Thisfunctionalityisusefulwhendebuggingtestruns.Theproperty"message"definesthetextthatisprinted.Testermightuseittoprintoutdebugmessagesandvariablesasshownthenextcodeexample:
XMLDSL
<testcasename="echoTest"><variables><variablename="date"value="citrus:currentDate()"/></variables><actions><echo><message>HelloTestFramework</message></echo>
<echo><message>Currentdateis:$date</message></echo></actions></testcase>
JavaDSLdesignerandrunner
@CitrusTestpublicvoidechoTest()variable("date","citrus:currentDate()");
echo("HelloTestFramework");echo("Currentdateis:$date");
Resultontheconsole:
HelloTestFrameworkCurrenttimeis:05.08.2008
CitrusReferenceGuide
146Echo
![Page 147: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/147.jpg)
Stoptime
Timemeasurementduringatestcanbeveryhelpful.Theactioncreatesandmonitorsmultipletimelines.Theactionofferstheattributeidtoidentifyatimeline.Thetestercanofcourseusemorethanonetimelinewithdifferentidssimultaneously.
Readthenextexampleandyouwillunderstandthemixofdifferenttimelines:
XMLDSL
<testcasename="StopTimeTest"><actions><trace-time/>
<trace-timeid="time_line_id"/>
<sleepseconds="3.5"/>
<trace-timeid="time_line_id"/>
<sleepmilliseconds="5000"/>
<trace-time/>
<trace-timeid="time_line_id"/></actions></testcase>
JavaDSL
@CitrusTestpublicvoidstopTimeTest()stopTime();stopTime("time_line_id");sleep(3.5);//dosomethingstopTime("time_line_id");sleep(5000);//dosomethingstopTime();stopTime("time_line_id");
Thetestoutputlookslikefollows:
StartingTimeWatcher:StartingTimeWatcher:time_line_id
CitrusReferenceGuide
147Stoptime
![Page 148: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/148.jpg)
TimeWatchertime_line_idafter3500millisecondsTimeWatcherafter8500secondsTimeWatchertime_line_idafter8500milliseconds
ImportantTimelineidsshouldnotexistastestvariablesbeforetheactioniscalledforthefirsttime.Thiswouldbreakthetimelineinitialization.
NoteIncasenotimelineidisspecifiedtheframeworkwillmeasurethetimeforadefaulttimeline.Toprintoutthecurrentelapsedtimeforatimelineyousimplyhavetoplacethe`actionintotheactionchainagainandagain,usingtherespectivetimelineidentifier.Theelapsedtimewillbeprintedouttotheconsoleeverytime.
Eachtimelineisstoredastestvariableinthetestcase.Bydefaultyouwillhavethefollowingtestvariablessetforeachtimeline:
CITRUS_TIMELINEfirsttimestampoftimelineCITRUS_TIMELINE_VALUElatesttimemeasurementvalue(timepassedsincefirsttimestampinmilliseconds)
Accordingtoyourtimelineidyouwillgetdifferenttestvariablenames.Alsoyoucancustomizethetimevaluesuffix(default:_VALUE):
XMLDSL
<trace-timeid="custom_watcher"suffix="_1st"/><sleep/><trace-timeid="custom_watcher"suffix="_2nd"/>
JavaDSL
@CitrusTeststopTime("custom_watcher","_1st");sleep();stopTime("custom_watcher","_2nd");
Youwillgetfollowingtestvariablesset:
custom_watcherfirsttimestampoftimelinecustom_watcher_1sttimepassedsincestartcustom_watcher_2ndtimepassedsincestart
Ofcourseusingthesamesuffixmultipletimeswilloverwritethetimestampsintestvariables.
CitrusReferenceGuide
148Stoptime
![Page 149: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/149.jpg)
CitrusReferenceGuide
149Stoptime
![Page 150: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/150.jpg)
Createvariables
Asyouknowvariablesusuallyaredefinedatthebeginningofthetestcase(testcase-variables).Itmightalsobehelpfultoresetexistingvariablesaswellastodefinenewvariablesduringthetest.Theactionisabletodeclarenewvariablesoroverwriteexistingones.
XMLDSL
<testcasename="createVariablesTest"><variables><variablename="myVariable"value="12345"/><variablename="id"value="54321"/></variables><actions><echo><message>Currentvariablevalue:$myVariable</message></echo>
<create-variables><variablename="myVariable"value="$id"/><variablename="newVariable"value="'thisisatest'"/></create-variables>
<echo><message>Currentvariablevalue:$myVariable</message></echo>
<echo><message>Newvariable'newVariable'hasthevalue:$newVariable</message></echo></actions></testcase>
JavaDSLdesignerandrunner
@CitrusTestpublicvoidcreateVariableTest()variable("myVariable","12345");variable("id","54321");
echo("Currentvariablevalue:$myVariable");
createVariable("myVariable","$id");
CitrusReferenceGuide
150Createvariables
![Page 151: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/151.jpg)
createVariable("newVariable","thisisatest");
echo("Currentvariablevalue:$myVariable");
echo("Newvariable'newVariable'hasthevalue:$newVariable");
NotePleasenotethedifferencebetweenthevariable()methodandthecreateVariable()method.Thefirstinitializesthetestcasewiththetestvariables.Soallvariablesdefinedwiththismethodarevalidfromtheverybeginningofthetest.IncontrarytothatthecreateVariable()isexecutedwithinthetestactionchain.Thenewlycreatedvariablesarethenvalidfortherestofthetest.Trailingactionscanreferencethevariablesasusualwiththevariableexpression.
CitrusReferenceGuide
151Createvariables
![Page 152: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/152.jpg)
Tracevariables
Youalreadyknowtheactionthatprintsmessagestotheconsoleorlogger.Theactionisspeciallydesignedtotraceallcurrentlyvalidtestvariablestotheconsole.Thiswasmainlyusedbyusfordebugreasons.Theusageisquitesimple:
XMLDSL
<testcasename="traceVariablesTest"><variables><variablename="myVariable"value="12345"/><variablename="nextVariable"value="54321"/></variables><actions><trace-variables><variablename="myVariable"/><variablename="nextVariable"/></trace-variables>
<trace-variables/></actions></testcase>
JavaDSLdesignerandrunner
@CitrusTestpublicvoidtraceTest()variable("myVariable","12345");variable("nextVariable","54321");
traceVariables("myVariable","nextVariable");traceVariables();
Simplyaddtheactiontoyouractionchainandallvariableswillbeprintedouttotheconsole.Youareabletodefineaspecialsetofvariablesbyusingthechildelements.Seetheoutputthatwasgeneratedbythetestexampleabove:
CurrentvalueofvariablemyVariable=12345CurrentvalueofvariablenextVariable=54321
CitrusReferenceGuide
152Trace
![Page 153: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/153.jpg)
CitrusReferenceGuide
153Trace
![Page 154: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/154.jpg)
Transform
The<transform>actiontransformsXMLfragmentswithXSLTinordertoconstructvariousXMLrepresentations.Thetransformationresultisstoredintoatestvariableforfurtherusage.Thepropertyxml-datadefinestheXMLsource,thatisgoingtobetransformed,whilexslt-datadefinestheXSLTtransformationrules.Theattributevariablespecifiesthetargettestvariablewhichreceivesthetransformationresult.ThetestermightusetheactiontotransformXMLmessagesasshowninthenextcodeexample:
XMLDSL
<testcasename="transformTest"><actions><transformvariable="result"><xml-data><![CDATA[<TestRequest><Message>HelloWorld!</Message></TestRequest>]]></xml-data><xslt-data><![CDATA[<xsl:stylesheetversion="1.0"xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:templatematch="/"><html><body><h2>TestRequest</h2><p>Message:<xsl:value-ofselect="TestRequest/Message"/></p></body></html></xsl:template></xsl:stylesheet>]]></xslt-data></transform><echo><message>$result</message></echo></actions></testcase>
Thetransformationaboveresultsto:
CitrusReferenceGuide
154Transform
![Page 155: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/155.jpg)
<html><body><h2>TestRequest</h2><p>Message:HelloWorld!</p></body></html>
IntheexampleweusedCDATAsectionstodefinethetransformationsourceaswellastheXSLtransformationrules.Asusualyoucanalsouseexternalfileresourceshere.Thetransformactionwithexternalfileresourceslookslikefollows:
<transformvariable="result"><xml-resourcefile="classpath:transform-source.xml"/><xslt-resourcefile="classpath:transform.xslt"/></transform>
TheJavaDSLalternativefortransformingdataviaXSTLinCitruslookslikefollows:
JavaDSLdesigner
@CitrusTestpublicvoidtransformTest()transform().source("<TestRequest>"+"<Message>HelloWorld!</Message>"+"</TestRequest>").xslt("<xsl:stylesheetversion=\"1.0\"xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">\n""<xsl:templatematch=\"/\">\n"+"<html>\n"+"<body>\n"+"<h2>TestRequest</h2>\n"+"<p>Message:<xsl:value-ofselect=\"TestRequest/Message\"/></p>\n""</body>\n"+"</html>\n"+"</xsl:template>\n"+"</xsl:stylesheet>").result("result");
echo("$result");
transform().source(newClassPathResource("com/consol/citrus/actions/transform-source.xml")).xslt(newClassPathResource("com/consol/citrus/actions/transform.xslt")).result("result");
CitrusReferenceGuide
155Transform
![Page 156: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/156.jpg)
echo("$result");
JavaDSLrunner
@CitrusTestpublicvoidtransformTest()transform(action->action.source("<TestRequest>"+"<Message>HelloWorld!</Message>"+"</TestRequest>").xslt("<xsl:stylesheetversion=\"1.0\"xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">\n""<xsl:templatematch=\"/\">\n"+"<html>\n"+"<body>\n"+"<h2>TestRequest</h2>\n"+"<p>Message:<xsl:value-ofselect=\"TestRequest/Message\"/></p>\n"+"</body>\n"+"</html>\n"+"</xsl:template>\n"+"</xsl:stylesheet>").result("result"));
echo("$result");
transform(action->action.source(newClassPathResource("com/consol/citrus/actions/transform-source.xml")).xslt(newClassPathResource("com/consol/citrus/actions/transform.xslt")).result("result"));
echo("$result");
Definingmulti-lineStringswithnestedquotesisnofuninJava.Soyoumaywanttouseexternalfileresourcesforyourscriptsasshowninthesecondpartoftheexample.InfactyoucouldalsousescriptlanguageslikeGroovyorScalathathavemuchbettersupportformulti-lineStrings.
CitrusReferenceGuide
156Transform
![Page 157: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/157.jpg)
Groovyscriptexecution
GroovyisanagiledynamiclanguagefortheJavaPlatform.GroovyshipswithalotofverypowerfulfeaturesandfitsperfectlywithJavaasitisbasedonJavaandrunsinsidetheJVM.
TheCitrusGroovysupportmightbetheentranceforyoutowritecustomizedtestactions.YoucaneasilyexecuteGroovycodeinsideatestcase,justlikeanormaltestaction.ThewholetestcontextwithallvariablesisavailabletotheGroovyaction.Thismeanssomeonecanchangevariablevaluesorcreatenewvariablesveryeasily.
Let'shavealookatsomeexamplesinordertounderstandthepossibleGroovycodeinteractionsinCitrus:
XMLDSL
<testcasename="groovyTest"><variables><variablename="time"value="citrus:currentDate()"/></variables><actions><groovy>println'HelloCitrus'</groovy><groovy>println'Thevariableis:$time'</groovy><groovyresource="classpath:com/consol/citrus/script/example.groovy"/></actions></testcase>
JavaDSLdesigner
@CitrusTestpublicvoidgroovyTest()groovy("println'HelloCitrus'");groovy("println'Thevariableis:$time'");
groovy(newClassPathResource("com/consol/citrus/script/example.groovy"));
JavaDSLrunner
@CitrusTest
CitrusReferenceGuide
157Groovy
![Page 158: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/158.jpg)
publicvoidgroovyTest()groovy(action->action.script("println'HelloCitrus'"));groovy(action->action.script("println'Thevariableis:$time'"));
groovy(action->action.script(newClassPathResource("com/consol/citrus/script/example.groovy"
AsyoucanseeitispossibletowriteGroovycodedirectlyintothetestcase.CitruswillinterpretandexecutetheGroovycodeatruntime.Asusualnestedvariableexpressionsarereplacedwithrespectivevalues.IngeneralthisisdoneinadvancebeforetheGroovycodeisinterpreted.FormorecomplexGroovycodesectionswhichgrowinlinesofcodeyoucanalsoreferenceexternalfileresources.
AfterthisbasicGroovycodeusageinsideatestcasewemightbeinterestedaccessingthewholeTestContext.TheTestContextJavaobjectholdsalltestvariablesandfunctiondefinitionsforthetestcaseandcanbereferencedinGroovycodeviasimplenamingconvention.Justaccesstheobjectreference'context'andyouareabletomanipulatetheTestContext(e.g.settinganewvariablewhichisdirectlyreadyforuseinfollowingtestactions).
XMLDSL
<testcasename="groovyTest"><actions><groovy>context.setVariable("greetingText","HelloCitrus")printlncontext.getVariable("greetingText")</groovy><echo><message>Newvariable:$greetingText</message></echo></actions></testcase>
NoteTheimplicitTestContextaccessthatwasshownintheprevioussampleworkswithadefaultGroovyscripttemplateprovidedbyCitrus.TheGroovycodeyouwriteinthetestcaseisautomaticallysurroundedwithaGroovyscriptwhichtakescareofhandlingtheTestContext.Thedefaulttemplatelookslikefollows:
importcom.consol.citrus.*importcom.consol.citrus.variable.*importcom.consol.citrus.context.TestContextimportcom.consol.citrus.script.GroovyAction.ScriptExecutor
CitrusReferenceGuide
158Groovy
![Page 159: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/159.jpg)
publicclassGScriptimplementsScriptExecutorpublicvoidexecute(TestContextcontext)@SCRIPTBODY@
Yourcodeisplacedinsubstitutiontothe@SCRIPTBODY@placeholder.NowyoumightunderstandhowCitrushandlesthecontextautomatically.YoucanalsowriteyourownscripttemplatesmakingmoreadvancedusageofotherJavaAPIsandGroovycode.Justaddascripttemplatepathtothetestactionlikethis:
<groovyscript-template="classpath:my-custom-template.groovy">[...]</groovy>
Ontheotherhandyoucandisabletheautomaticscripttemplatewrappinginyouractionatall:
<groovyuse-script-template="false">println'JustusesomeGroovycode'</groovy>
ThenextexampledealswithadvancedGroovycodeandwritingwholeclasses.WewriteanewGroovyclasswhichimplementstheScriptExecutorinterfaceofferedbyCitrus.ThisinterfacedefinesaspecialexecutemethodandprovidesaccesstothewholeTestContextforadvancedtestvariablesaccess.
<testcasename="groovyTest"><variables><variablename="time"value="citrus:currentDate()"/></variables><actions><groovy><![CDATA[importcom.consol.citrus.*importcom.consol.citrus.variable.*importcom.consol.citrus.context.TestContextimportcom.consol.citrus.script.GroovyAction.ScriptExecutor
publicclassGScriptimplementsScriptExecutorpublicvoidexecute(TestContextcontext)printlncontext.getVariable("time")
CitrusReferenceGuide
159Groovy
![Page 160: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/160.jpg)
]]></groovy></actions></testcase>
ImplementingtheScriptExecutorinterfaceinacustomGroovyclassisapplicableforveryspecialtestcontextmanipulationsasyouareabletoimportanduseotherJavaAPIclassesinthiscode.
CitrusReferenceGuide
160Groovy
![Page 161: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/161.jpg)
Failingthetest
Thefailactionwillgenerateanexceptioninordertoterminatethetestcasewitherror.Thetestcasewillthereforenotbesuccessfulinthereports.
Theusercanspecifyacustomerrormessagefortheexceptioninordertodescribetheerrorcause.Hereisaverysimpleexampletoclarifythesyntax:
XMLDSL
<testcasename="failTest"><actions><failmessage="Testwillfailwithcustommessage"/></actions></testcase>
Testresults:
Executionoftest:failTestfailed!Nestedexceptionis:com.consol.citrus.exceptions.CitrusRuntimeException:Testwillfailwithcustommessage
[...]
CITRUSTESTRESULTS
failTest:failed-Exceptionis:Testwillfailwithcustommessage
Found1testcasestoexecuteSkipped0testcases(0.0%)Executed1testcases,containing3actionsTestsfailed:1(100.0%)Testssuccessfully:0(0.0%)
WhileusingtheJavaDSLtestermightwanttoraisesomeJavaexceptionsinthemiddleofconfiguringthetestcase.Butthisisnotpossibleaswehavetoseparatethedesigntimeandtheexecutiontimeofthetestcase.The@CitrusTestannotatedconfigurationmethodiscalledforbuildingupthewholetestcase.Afterthismethodwasprocessedthetestgetsexecutedinruntimeoththetest.Ifyouspecifyathrowsexceptionstatementintheconfigurationmethodthiswillnotbedoneatruntimebutatdesigntime.ThisiswhyyouhavetousethespecialfailtestactionwhichraisesaJavaexceptionduringtheruntimeofthetest.Thenextexamplewillnotworkasexpected:
CitrusReferenceGuide
161Fail
![Page 162: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/162.jpg)
JavaDSLdesignerandrunner
@CitrusTestpublicvoidwrongUsageSample()//sometestactions
thrownewValidationException("Thistestshouldfailnow");//doesnotworkasexpected
Thevalidationexceptionaboveisdirectlyraisedbeforethetestisabletostartasthe@CitrusTestannotatedmethoddoesnotrepresentthetestruntime.Insteadofthiswehavetousethefailactionasfollows:
JavaDSLdesignerandrunner
@CitrusTestpublicvoidfailTest()//sometestactions
fail("Thistestshouldfailnow");//failsattestruntimeasexpected
Nowthetestfailsatruntimeasthefailactionisraisedduringthetestexecutionasexpected.
CitrusReferenceGuide
162Fail
![Page 163: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/163.jpg)
Input
Duringthetestcaseexecutionitispossibletoreadsomeuserinputfromthecommandline.Thetestexecutionwillstopandwaitforkeyboardinputsoverthestandardinputstream.Theuserhastotypetheinputandenditwiththereturnkey.
Theuserinputisstoredtotherespectivevariablevalue.
XMLDSL
<testcasename="inputTest"><variables><variablename="userinput"value=""></variable><variablename="userinput1"value=""></variable><variablename="userinput2"value="y"></variable><variablename="userinput3"value="yes"></variable><variablename="userinput4"value=""></variable></variables><actions><input/><echo><message>userinputwas:$userinput</message></echo>
<inputmessage="Nowpressenter:"variable="userinput1"/><echo><message>userinputwas:$userinput1</message></echo>
<inputmessage="Doyouwanttocontinue?"valid-answers="y/n"variable="userinput2"/><echo><message>userinputwas:$userinput2</message></echo>
<inputmessage="Doyouwanttocontinue?"valid-answers="yes/no"variable="userinput3"/><echo><message>userinputwas:$userinput3</message></echo>
<inputvariable="userinput4"/><echo><message>userinputwas:$userinput4</message></echo></actions></testcase>
Asyoucanseetheinputactioniscustomizablewithapromptmessagethatisdisplayedtotheuserandsomevalidanswerpossibilities.Theuserinputisstoredtoatestvariableforfurtheruseinthetestcase.Indetailtheinputactionoffersfollowingattributes:
message->messagedisplayedtotheuser
valid-answers->optionalslashseparatedstringcontainingthepossiblevalidanswers
CitrusReferenceGuide
163Input
![Page 164: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/164.jpg)
variable->resultvariablenameholdingtheuserinput(default=$userinput)
ThesameactioninJavaDSLnowlooksquitefamiliartousalthoughattributenamingisslightlydifferent:
JavaDSLdesigner
@CitrusTestpublicvoidinputActionTest()variable("userinput","");variable("userinput1","");variable("userinput2","y");variable("userinput3","yes");variable("userinput4","");
input();echo("userinputwas:$userinput");input().message("Nowpressenter:").result("userinput1");echo("userinputwas:$userinput1");input().message("Doyouwanttocontinue?").answers("y","n").result("userinput2");echo("userinputwas:$userinput2");input().message("Doyouwanttocontinue?").answers("yes","no").result("userinput3");echo("userinputwas:$userinput3");input().result("userinput4");echo("userinputwas:$userinput4");
JavaDSLrunner
@CitrusTestpublicvoidinputActionTest()variable("userinput","");variable("userinput1","");variable("userinput2","y");variable("userinput3","yes");variable("userinput4","");
input(action->);echo("userinputwas:$userinput");input(action->action.message("Nowpressenter:").result("userinput1"));echo("userinputwas:$userinput1");input(action->action.message("Doyouwanttocontinue?").answers("y","n").result("userinput2"echo("userinputwas:$userinput2");input(action->action.message("Doyouwanttocontinue?").answers("yes","no").result("userinput3"echo("userinputwas:$userinput3");input(action->action.result("userinput4"));echo("userinputwas:$userinput4");
CitrusReferenceGuide
164Input
![Page 165: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/165.jpg)
Whentheuserinputisrestrictedtoasetofvalidanswerstheinputvalidationofcoursecanfailduetomismatch.Thisisthecasewhentheuserprovidessomeinputnotmatchingthevalidanswersgiven.Inthiscasetheuserisagainaskedtoprovidevalidinput.Thetestactionwillcontinuetoaskforvalidinputuntilavalidanswerisgiven.
NoteUserinputsmaynotfittoautomatictestingintermsofcontinuousintegrationtestingwherenouserispresenttotypeinthecorrectansweroverthekeyboard.Inthiscaseyoucanalwaysskiptheuserinputinadvancebyspecifyingavariablethatmatchestheuserinputvariablename.Astheuserinputvariableisthenalreadypresenttheuserinputismissedoutandthetestproceedsautomatically.
CitrusReferenceGuide
165Input
![Page 166: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/166.jpg)
Load
Youareabletoloadpropertiesfromexternalpropertyfilesandstorethemastestvariables.Theactionwillrequireafileresourceeitherfromclasspathorfilesysteminordertoreadthepropertyvalues.
Letuslookatanexampletogetanideaaboutthisaction:
Contentofload.properties:
username=MickeyMousegreeting.text=HelloTestFramework
XMLDSL
<testcasename="loadPropertiesTest"><actions><load><propertiesfile="file:tests/resources/load.properties"/></load>
<trace-variables/></actions></testcase>
JavaDSLdesignerandrunner
@CitrusTestpublicvoidloadPropertiesTest()load("file:tests/resources/load.properties");
traceVariables();
Output:
Currentvalueofvariableusername=MickeyMouseCurrentvalueofvariablegreeting.text=HelloTestFramework
Theactionwillloadallavailablepropertiesinthefileload.propertiesandstorethemtothetestcaseaslocalvariables.
CitrusReferenceGuide
166Load
![Page 167: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/167.jpg)
ImportantPleasebeawareofthefactthatexistingvariablesareoverwritten!
CitrusReferenceGuide
167Load
![Page 168: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/168.jpg)
Wait
Withthisactionyoucanmakeyourtestwaituntilacertainconditionissatisfied.Theattributesecondsdefinestheamountoftimetowaitinseconds.Youcanalsousethemillisecondsattributeforamorefinegrainedtimevalue.Theattributeintervaldefinestheamountoftimetowaitbetweeneachcheck.Theintervalisalwaysspecifiedasmillisecondtimeinterval.
Ifthecheckdoesnotexceedwithinthedefinedoverallwaitingtimethenthetestexecutionfailswithanappropriateerrormessage.Therearedifferenttypesofconditionstocheck.
http:ThisconditionisbasedonaHttprequestcallonaserverendpoint.CitruswillwaituntiltheHttpresponseisasdefined(e.g.Http200OK).Thisisusefulwhenyouwanttowaitforaservertostart.file:Thisconditionchecksfortheexistenceofafileonthelocalfilesystem.Citruswillwaituntilthefileispresent.message:Thisconditionchecksfortheexistenceofamessageinthelocalmessagestoreofthecurrenttestcase.Citruswillwaituntilthemessagewiththegivennameispresent.
Nextletushavealookatasimpleexample:
XMLDSL
<testcasename="waitTest"><actions><waitseconds="10"interval="2000"><httpurl="http://sample.org/resource"statusCode="200"timeout="2000"/><wait/></actions></testcase>
JavaDSLdesignerandrunner
@CitrusTestpublicvoidwaitTest()waitFor().http("http://sample.org/resource").seconds(10L).interval(2000L);
CitrusReferenceGuide
168Wait
![Page 169: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/169.jpg)
TheexamplewaitsforsomeHttpserverresourcetobeavailablewithHttp200OKresponse.CitruswilluseHEADrequestmethodbydefault.YoucansettherequestmethodwiththemethodattributeontheHttpcondition.
Nextletushavealookatthefileconditionusage:
XMLDSL
<testcasename="waitTest"><actions><waitseconds="10"interval="2000"><filepath="path/to/resource/file.txt"/><wait/></actions></testcase>
JavaDSLdesignerandrunner
@CitrusTestpublicvoidwaitTest()waitFor().file("path/to/resource/file.txt");
Citruschecksforthefiletoexistunderthegivenpath.Onlyifthefileexiststhetestwillcontinuewithfurthertestactions.
Nextletushavealookatthemessageconditionusage:
XMLDSL
<testcasename="waitTest"><actions><waitseconds="10"interval="2000"><messagename="helloRequest"/><wait/></actions></testcase>
JavaDSLdesignerandrunner
@CitrusTestpublicvoidwaitTest()waitFor().message("helloRequest");
CitrusReferenceGuide
169Wait
![Page 170: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/170.jpg)
CitruschecksforthemessagewiththenamehelloRequestinthelocalmessagestore.Onlyifthemessagewiththegivennameisfoundthetestwillcontinuewithfurthertestactions.Thelocalmessagestoreisautomaticallyfilledwithallexchangedmessages(sendorreceive)inatestcase.Themessagenamesaredefinedintherespectivesendorreceiveoperationsinthetest.
Whenshouldsomebodyusethisaction?Thisactionisveryusefulwhenyouwantyourtesttowaitforacertaineventtooccurbeforecontinuingwiththetestexecution.ForexampleifyouwishthatyourtestwaitsuntilaDockercontainerisstartedorforanapplicationtocreatealogfilebeforecontinuing,thenusethisaction.Youcanalsocreateyourownconditionstatementsandbindittothetestaction.
CitrusReferenceGuide
170Wait
![Page 171: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/171.jpg)
PurgingJMSdestinations
PurgingJMSdestinationsduringthetestrunisquiteessential.DifferenttestcasescaninfluenceeachotherwhensendingmessagestothesameJMSdestinations.Atestcaseshouldonlyreceivethosemessagesthatactuallybelongtoit.ThereforeitisagoodideatopurgeallJMSqueuedestinationsbetweenthetestcases.ObsoletemessagesthatarestuckinaJMSqueueforsomereasonarethenremovedsothatthefollowingtestcaseisnotoffended.
NoteCitrusprovidesspecialsupportforJMSrelatedfeatures.WehavetoactivatethoseJMSfeaturesinourtestcasebyaddingaspecial"jms"namespaceandschemadefinitionlocationtothetestcaseXML.
<spring:beansxmlns="http://www.citrusframework.org/schema/testcase"xmlns:spring="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:jms="http://www.citrusframework.org/schema/jms/testcase"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.citrusframework.org/schema/testcasehttp://www.citrusframework.org/schema/testcase/citrus-testcase.xsdhttp://www.citrusframework.org/schema/jms/testcasehttp://www.citrusframework.org/schema/jms/testcase/citrus-jms-testcase.xsd">
[...]
</beans>
NowwearereadytousetheJMSfeaturesinourtestcaseinordertopurgesomeJMSqueues.Thiscanbedonewithfollowingactiondefinition:
XMLDSL
<testcasename="purgeTest"><actions><jms:purge-jms-queues><jms:queuename="Some.JMS.QUEUE.Name"/><jms:queuename="Another.JMS.QUEUE.Name"/><jms:queuename="My.JMS.QUEUE.Name"/></jms:purge-jms-queues>
<jms:purge-jms-queuesconnection-factory="connectionFactory"><jms:queuename="Some.JMS.QUEUE.Name"/><jms:queuename="Another.JMS.QUEUE.Name"/>
CitrusReferenceGuide
171PurgeJMSqueues
![Page 172: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/172.jpg)
<jms:queuename="My.JMS.QUEUE.Name"/></jms:purge-jms-queues></actions></testcase>
Noticethatwehavereferencedthejmsnamespacewhenusingthepurge-jms-queuestestaction.
JavaDSLdesigner
@Autowired@Qualifier("connectionFactory")privateConnectionFactoryconnectionFactory;
@CitrusTestpublicvoidpurgeTest()purgeQueues().queue("Some.JMS.QUEUE.Name").queue("Another.JMS.QUEUE.Name");
purgeQueues(connectionFactory).timeout(150L)//customtimeoutinms.queue("Some.JMS.QUEUE.Name").queue("Another.JMS.QUEUE.Name");
JavaDSLrunner
@Autowired@Qualifier("connectionFactory")privateConnectionFactoryconnectionFactory;
@CitrusTestpublicvoidpurgeTest()purgeQueues(action->action.queue("Some.JMS.QUEUE.Name").queue("Another.JMS.QUEUE.Name"));
purgeQueues(action->action.connectionFactory(connectionFactory).timeout(150L)//customtimeoutinms.queue("Some.JMS.QUEUE.Name").queue("Another.JMS.QUEUE.Name"));
CitrusReferenceGuide
172PurgeJMSqueues
![Page 173: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/173.jpg)
PurgingtheJMSqueuesineverytestcaseisquiteexhaustingbecauseeverytestcaseneedstodefineapurgingactionattheverybeginningofthetest.Fortunatelythetestsuitedefinitionofferstaskstorunbefore,betweenandafterthetestcaseswhichshouldeaseupthistasksalot.Thetestsuiteoffersaverysimplewaytopurgethedestinationsbetweenthetests.Seetestsuite-before-testformoreinformationaboutthis.
AsyoucanseeinthenextexampleitisquiteeasytospecifyagroupofdestinationsintheSpringconfigurationthatgetpurgedbeforeatestisexecuted.
<citrus:before-testid="purgeBeforeTest"><citrus:actions><jms:purge-jms-queues><jms:queuename="Some.JMS.QUEUE.Name"/><jms:queuename="Another.JMS.QUEUE.Name"/></jms:purge-jms-queues></citrus:actions></citrus:before-test>
NotePleasekeepinmindthattheJMSrelatedconfigurationcomponentsinCitrusbelongtoaseparateXMLnamespacejms:.WehavetoaddthisnamespacedeclarationtoeachtestcaseXMLandSpringbeanXMLconfigurationfileasdescribedattheverybeginningofthissection.
Thesyntaxforpurgingthedestinationsisthesameasweuseditinsidethetestcase.SonowweareabletopurgeJMSdestinationswithgivendestinationnames.ButsometimeswedonotwanttorelyonqueueortopicnamesasweretrievedestinationsoverJNDIforinstance.WecandealwithdestinationscomingfromJNDIlookuplikefollows:
<jee:jndi-lookupid="jmsQueueHelloRequestIn"jndi-name="jms/jmsQueueHelloRequestIn"/><jee:jndi-lookupid="jmsQueueHelloResponseOut"jndi-name="jms/jmsQueueHelloResponseOut"/>
<citrus:before-testid="purgeBeforeTest"><citrus:actions><jms:purge-jms-queues><jms:queueref="jmsQueueHelloRequestIn"/><jms:queueref="jmsQueueHelloResponseOut"/></jms:purge-jms-queues></citrus:actions></citrus:before-test>
CitrusReferenceGuide
173PurgeJMSqueues
![Page 174: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/174.jpg)
Wejustusetheattribute'ref'insteadof'name'andCitrusislookingforabeanreferenceforthatidentifierthatresolvestoaJMSdestination.YoucanusetheJNDIbeanreferencesinsideatestcase,too.
XMLDSL
<testcasename="purgeTest"><actions><jms:purge-jms-queues><jms:queueref="jmsQueueHelloRequestIn"/><jms:queueref="jmsQueueHelloResponseOut"/></jms:purge-jms-queues></actions></testcase>
OfcourseyoucanusequeueobjectreferencesalsoinJavaDSLtestcases.HereweeasilycanuseSpring'sdependencyinjectionwithautowiringtogettheobjectreferencesfromtheIoCcontainer.
JavaDSLdesigner
@Autowired@Qualifier("jmsQueueHelloRequestIn")privateQueuejmsQueueHelloRequestIn;
@Autowired@Qualifier("jmsQueueHelloResponseOut")privateQueuejmsQueueHelloResponseOut;
@CitrusTestpublicvoidpurgeTest()purgeQueues().queue(jmsQueueHelloRequestIn).queue(jmsQueueHelloResponseOut);
JavaDSLrunner
@Autowired@Qualifier("jmsQueueHelloRequestIn")privateQueuejmsQueueHelloRequestIn;
@Autowired@Qualifier("jmsQueueHelloResponseOut")privateQueuejmsQueueHelloResponseOut;
CitrusReferenceGuide
174PurgeJMSqueues
![Page 175: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/175.jpg)
@CitrusTestpublicvoidpurgeTest()purgeQueues(action->action.queue(jmsQueueHelloRequestIn).queue(jmsQueueHelloResponseOut));
NoteYoucanmixqueuenameandqueueobjectreferencesasyoulikewithinonesinglepurgequeuetestaction.
CitrusReferenceGuide
175PurgeJMSqueues
![Page 176: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/176.jpg)
Purgingmessagechannels
MessagechannelsdefinecentralmessagingdestinationsinCitrus.Thesearenamelyinmemorymessagequeuesholdingmessagesfortestcases.Thesemessagesmaybecomeobsoleteduringatestrun,especiallywhentestcasesfailandstopintheirmessageconsumption.Purgingthesemessagechanneldestinationsisessentialinthesescenariosinordertonotinfluenceupcomingtestcases.Eachtestcaseshouldonlyreceivethosemessagesthatactuallyrefertothetestmodel.Thereforeitisagoodideatopurgeallmessagechanneldestinationsbetweenthetestcases.Obsoletemessagesthatgetstuckinamessagechanneldestinationforsomereasonarethenremovedsothatupcomingtestcasearenotbroken.
Followingactiondefinitionpurgesallmessagesfromalistofmessagechannels:
XMLDSL
<testcasename="purgeChannelTest"><actions><purge-channel><channelname="someChannelName"/><channelname="anotherChannelName"/></purge-channel>
<purge-channel><channelref="someChannel"/><channelref="anotherChannel"/></purge-channel></actions></testcase>
AsyoucanseethetestactionsupportschannelnamesaswellaschannelreferencestoSpringbeaninstances.WhenusingchannelreferencesyourefertotheSpringbeanidornameinyourapplicationcontext.
TheJavaDSLworksquitesimilarasyoucanreadfromnextexamples:
JavaDSLdesigner
@Autowired@Qualifier("channelResolver")privateDestinationResolver<MessageChannel>channelResolver;
@CitrusTestpublicvoidpurgeTest()
CitrusReferenceGuide
176Purgechannels
![Page 177: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/177.jpg)
purgeChannels().channelResolver(channelResolver).channelNames("ch1","ch2","ch3").channel("ch4");
JavaDSLrunner
@Autowired@Qualifier("channelResolver")privateDestinationResolver<MessageChannel>channelResolver;
@CitrusTestpublicvoidpurgeTest()purgeChannels(action->action.channelResolver(channelResolver).channelNames("ch1","ch2","ch3").channel("ch4"));
Thechannelresolverreferenceisoptional.BydefaultCitruswillautomaticallyuseaSpringapplicationcontextchannelresolversoyoujusthavetousetherespectiveSpringbeannamesthatareconfiguredintheSpringapplicationcontext.Howeversettingacustomchannelresolvermaybeadequateforyouinsomespecialcases.
WhilespeakingofSpringapplicationcontextbeanreferencesthenextexampleusessuchbeanreferencesforchannelstopurge.
JavaDSLdesigner
@Autowired@Qualifier("channel1")privateMessageChannelchannel1;
@Autowired@Qualifier("channel2")privateMessageChannelchannel2;
@Autowired@Qualifier("channel3")privateMessageChannelchannel3;
@CitrusTestpublicvoidpurgeTest()purgeChannels().channels(channel1,channel2).channel(channel3);
CitrusReferenceGuide
177Purgechannels
![Page 178: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/178.jpg)
JavaDSLrunner
@Autowired@Qualifier("channel1")privateMessageChannelchannel1;
@Autowired@Qualifier("channel2")privateMessageChannelchannel2;
@Autowired@Qualifier("channel3")privateMessageChannelchannel3;
@CitrusTestpublicvoidpurgeTest()purgeChannels(action->action.channels(channel1,channel2).channel(channel3));
Messageselectorsenableyoutoselectivelyremovemessagesfromthedestination.Allmessagesthatpassthemessageselectionlogicgetdeletedtheothermessageswillremainunchangedinsidethechanneldestination.ThemessageselectorisaSpringbeanthatimplementsaspecialmessageselectorinterface.Apossibleimplementationcouldbeaselectordeletingallmessagesthatareolderthanfiveseconds:
importorg.springframework.messaging.Message;importorg.springframework.integration.core.MessageSelector;
publicclassTimeBasedMessageSelectorimplementsMessageSelector
publicbooleanaccept(Message<?>message)if(System.currentTimeMillis()-message.getHeaders().getTimestamp()>5000)returnfalse;elsereturntrue;
NoteThemessageselectorreturnsfalseforthosemessagesthatshouldbedeletedfromthechannel!
CitrusReferenceGuide
178Purgechannels
![Page 179: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/179.jpg)
YousimplydefinethemessageselectorasanewSpringbeanintheCitrusapplicationcontextandreferenceitinyourtestactionproperty.
<beanid="specialMessageSelector"class="com.consol.citrus.special.TimeBasedMessageSelector"/>
Nowletushavealookathowyoureferencetheselectorinyourtestcase:
XMLDSL
<purge-channelsmessage-selector="specialMessageSelector"><channelname="someChannelName"/><channelname="anotherChannelName"/></purge-channels>
JavaDSLdesigner
@Autowired@Qualifier("specialMessageSelector")privateMessageSelectorspecialMessageSelector;
@CitrusTestpublicvoidpurgeTest()purgeChannels().channelNames("ch1","ch2","ch3").selector(specialMessageSelector);
JavaDSLrunner
@Autowired@Qualifier("specialMessageSelector")privateMessageSelectorspecialMessageSelector;
@CitrusTestpublicvoidpurgeTest()purgeChannels(action->action.channelNames("ch1","ch2","ch3").selector(specialMessageSelector));
CitrusReferenceGuide
179Purgechannels
![Page 180: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/180.jpg)
IntheexamplesaboveweuseamessageselectorimplementationthatgetsinjectedviaSpringIoCcontainer.
Purgingchannelsineachtestcaseeverytimeisquiteexhaustingbecauseeverytestcaseneedstodefineapurgingactionattheverybeginningofthetest.Amorestraightforwardapproachwouldbetointroducesomepurgingactionwhichisautomaticallyexecutedbeforeeachtest.FortunatelytheCitrustestsuiteoffersaverysimplewaytodothis.Itisdescribedintestsuite-before-test.
Whenusingthespecialactionsequencebeforetestcasesweareabletopurgechanneldestinationseverytimeatestcaseexecutes.SeetheupcomingexampletofindouthowtheactionisdefinedintheSpringconfigurationapplicationcontext.
<citrus:before-testid="purgeBeforeTest"><citrus:actions><purge-channel><channelname="fooChannel"/><channelname="barChannel"/></purge-channel></citrus:actions></citrus:before-test>
Justusethisbefore-testbeanintheSpringbeanapplicationcontextandthepurgechannelactionisactive.Obsoletemessagesthatarewaitingonthemessagechannelsforconsumptionarepurgedbeforethenexttestinlineisexecuted.
TipPurgingmessagechannelsbecomesalsoveryinterestingwhenworkingwithserverinstancesinCitrus.Eachservercomponentautomaticallyhasaninboundmessagechannelwhereincomingmessagesarestoredtointernally.Soifyouneedtocleanupaserverthathasalreadystoredsomeincomingmessagesyoucandothiseasilybypurgingtheinternalmessagechannel.ThemessagechannelfollowsanamingconventionserverName.inboundwhereserverNameistheSpringbeannameoftheCitrusserverendpointcomponent.Ifyoupurgethisinternalchannelinabeforetestnatureyouaresurethatobsoletemessagesonaserverinstancegetpurgedbeforeeachtestisexecuted.
CitrusReferenceGuide
180Purgechannels
![Page 181: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/181.jpg)
Purgingendpoints
Citrusworkswithmessageendpointswhensendingandreceivingmessages.Ingeneralendpointscanalsoqueuemessages.ThisisespeciallythecasewhenusingJMSmessageendpointsoranyserverendpointcomponentinCitrus.Theseareinmemorymessagequeuesholdingmessagesfortestcases.Thesemessagesmaybecomeobsoleteduringatestrun,especiallywhenatestcasethatwouldconsumethemessagesfails.Deletingallmessagesfromamessageendpointisthereforeausefultaskandisessentialinsuchscenariossothatupcomingtestcasesarenotinfluenced.Eachtestcaseshouldonlyreceivethosemessagesthatactuallyrefertothetestmodel.Thereforeitisagoodideatopurgeallmessageendpointdestinationsbetweenthetestcases.Obsoletemessagesthatgetstuckinamessageendpointdestinationforsomereasonarethenremovedsothatupcomingtestcasearenotbroken.
Followingactiondefinitionpurgesallmessagesfromalistofmessageendpoints:
XMLDSL
<testcasename="purgeEndpointTest"><actions><purge-endpoint><endpointname="someEndpointName"/><endpointname="anotherEndpointName"/></purge-endpoint>
<purge-endpoint><endpointref="someEndpoint"/><endpointref="anotherEndpoint"/></purge-endpoint></actions></testcase>
AsyoucanseethetestactionsupportsendpointnamesaswellasendpointreferencestoSpringbeaninstances.WhenusingendpointreferencesyourefertotheSpringbeannameinyourapplicationcontext.
TheJavaDSLworksquitesimilar-havealook:
JavaDSLdesigner
@Autowired@CitrusTestpublicvoidpurgeTest()
CitrusReferenceGuide
181Purgeendpoints
![Page 182: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/182.jpg)
purgeEndpoints().endpointNames("endpoint1","endpoint2","endpoint3").endpoint("endpoint4");
JavaDSLrunner
@Autowired@CitrusTestpublicvoidpurgeTest()purgeEndpoints(action->action.endpointNames("endpoint1","endpoint2","endpoint3").endpoint("endpoint4"));
WhenusingtheJavaDSLwecaninjectendpointobjectswithSpringbeancontainerIoC.Thenextexampleusessuchbeanreferencesforendpointsinapurgeaction.
JavaDSLdesigner
@Autowired@Qualifier("endpoint1")privateEndpointendpoint1;
@Autowired@Qualifier("endpoint2")privateEndpointendpoint2;
@Autowired@Qualifier("endpoint3")privateEndpointendpoint3;
@CitrusTestpublicvoidpurgeTest()purgeEndpoints().endpoints(endpoint1,endpoint2).endpoint(endpoint3);
JavaDSLrunner
@Autowired@Qualifier("endpoint1")privateEndpointendpoint1;
@Autowired@Qualifier("endpoint2")
CitrusReferenceGuide
182Purgeendpoints
![Page 183: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/183.jpg)
privateEndpointendpoint2;
@Autowired@Qualifier("endpoint3")privateEndpointendpoint3;
@CitrusTestpublicvoidpurgeTest()purgeEndpoints(action->action.endpoints(endpoint1,endpoint2).endpoint(endpoint3));
Messageselectorsenableyoutoselectivelyremovemessagesfromanendpoint.Allmessagesthatmeetthemessageselectorconditiongetdeletedandtheothermessagesremaininsidetheendpointdestination.ThemessageselectoriseitheranormalStringname-valuerepresentationoramapofkeyvaluepairs:
XMLDSL
<purge-endpoints><selector><value>operation='sayHello'</value></selector><endpointname="someEndpointName"/><endpointname="anotherEndpointName"/></purge-endpoints>
JavaDSLdesigner
@CitrusTestpublicvoidpurgeTest()purgeEndpoints().endpointNames("endpoint1","endpoint2","endpoint3").selector("operation='sayHello'");
JavaDSLrunner
@CitrusTestpublicvoidpurgeTest()purgeEndpoints(action->action.endpointNames("endpoint1","endpoint2","endpoint3").selector("operation='sayHello'"));
CitrusReferenceGuide
183Purgeendpoints
![Page 184: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/184.jpg)
IntheexamplesaboveweuseaStringtorepresentthemessageselectorexpression.Ingeneralthemessageselectoroperatesonthemessageheader.SofollowingonfromthatweremoveallmessagesselectivelythathaveamessageheaderoperationwithitsvaluesayHello.
Purgingendpointsineachtestcaseeverytimeisquiteexhaustingbecauseeverytestcaseneedstodefineapurgingactionattheverybeginningofthetest.Amorestraightforwardapproachwouldbetointroducesomepurgingactionwhichisautomaticallyexecutedbeforeeachtest.FortunatelytheCitrustestsuiteoffersaverysimplewaytodothis.Itisdescribedintestsuite-before-test.
Whenusingthespecialactionsequencebeforetestcasesweareabletopurgeendpointdestinationseverytimeatestcaseexecutes.SeetheupcomingexampletofindouthowtheactionisdefinedintheSpringconfigurationapplicationcontext.
<citrus:before-testid="purgeBeforeTest"><citrus:actions><purge-endpoint><endpointname="fooEndpoint"/><endpointname="barEndpoint"/></purge-endpoint></citrus:actions></citrus:before-test>
Justusethisbefore-testbeanintheSpringbeanapplicationcontextandthepurgeendpointactionisactive.Obsoletemessagesthatarewaitingonthemessageendpointsforconsumptionarepurgedbeforethenexttestinlineisexecuted.
TipPurgingmessageendpointsbecomesalsoveryinterestingwhenworkingwithserverinstancesinCitrus.Eachservercomponentautomaticallyhasaninboundmessageendpointwhereincomingmessagesarestoredtointernally.Citruswillautomaticallyusethisincomingmessageendpointastargetforthepurgeactionsoyoucanjustusetheserverinstanceasyouknowitfromyourconfigurationinanypurgeaction.
CitrusReferenceGuide
184Purgeendpoints
![Page 185: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/185.jpg)
Assertfailure
CitrustestactionsfailwithJavaexceptionsanderrormessages.Thisgivesyoutheopportunitytoexpectanactiontofailduringtestexecution.YoucansimpleassertaJavaexceptiontobethrownduringexecution.Seetheexampleforanassertactiondefinitioninatestcase:
XMLDSL
<testcasename="assertFailureTest"><actions><assertexception="com.consol.citrus.exceptions.CitrusRuntimeException"message="Unknownvariable$date"><when><echo><message>Currentdateis:$date</message></echo></when></assert></actions></testcase>
JavaDSLdesignerandrunner
@CitrusTestpublicvoidassertTest()assertException().exception(com.consol.citrus.exceptions.CitrusRuntimeException.class).message("Unknownvariable$date").when(echo("Currentdateis:$date"));
NoteNotethattheassertactionrequiresanexception.Incasenoexceptionisthrownbytheembeddedtestactiontheassertionandthetestcasewillfail!
Theassertactionalwayswrapsasingletestaction,whichisthenmonitoredforfailure.Incasethenestedtestactionfailswitherroryoucanvalidatetheerrorinitstypeanderrormessage(optional).Thefailurehastofittheexpectedoneexactlyotherwisetheassertionfailsitself.
ImportantImportanttonoticeisthefactthatassertedexceptionsdonotcausefailureofthetestcase.Asyouexceptthefailuretohappenthetestcontinueswithitsworkoncetheassertionisdonesuccessfully.
CitrusReferenceGuide
185Assert
![Page 186: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/186.jpg)
CitrusReferenceGuide
186Assert
![Page 187: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/187.jpg)
Catchexceptions
InthepreviouschapterwehaveseenhowtoexpectfailuresinCitruswithassertaction.Nowtheassertactionisdesignedforsingleactionstobemonitoredandforfailurestobeexpectedinanycase.The'catch'actionincontrarycanholdseveralnestedtestactionsandexceptionfailureisoptional.
Thenestedactionsareerrorproofforthechosenexceptiontype.Thismeanspossibleexceptionsarecaughtandignored-thetestcasewillnotfailforthisexceptiontype.Butonlyforthisparticularexceptiontype!Otherexceptiontypesthatoccurduringexecutiondocausethetesttofailasusual.
XMLDSL
<testcasename="catchExceptionTest"><actions><catchexception="com.consol.citrus.exceptions.CitrusRuntimeException"><echo><message>Currentdateis:$date</message></echo></catch></actions></testcase>
JavaDSLdesignerandrunner
@CitrusTestpublicvoidcatchTest()catchException().exception(CitrusRuntimeException.class).when(echo("Currentdateis:$date"));
ImportantNotethatthereisnovalidationavailableinacatchblock.Socatchingexceptionsisjusttomakeatestmorestabletowardserrorsthatcanoccur.Thecaughtexceptiondoesnotcauseanyfailureinthetest.Thetestcasemaycontinuewithexecutionasiftherewasnotfailure.Alsonoticethatthecatchactionisalsohappywhennoexceptionatallisraised.Incontrarytothattheassertactionrequirestheexceptionandanassertactionisfailinginpositiveprocessing.
Catchingexceptionslikethismayonlyfittoveryerrorproneactionblockswherefailuresdonotharmthetestcasesuccess.Otherwiseafailureinatestactionshouldalwaysreflecttothewholetestcasetofailwitherrors.
CitrusReferenceGuide
187Catch
![Page 188: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/188.jpg)
NoteJavadevelopersmightaskwhynotusetry-catchJavablockinstead?Theanswerissimpleyetveryimportanttounderstand.ThetestmethodiscalledbytheJavaDSLtestcasebuilderforbuildingtheCitrustest.Thiscanbereferredtoasthedesigntimeofthetest.Afterthebuildingtestmethodwasprocessedthetestgetsexecuted,whichcanbecalledtheruntimeofthetest.Thismeansthatatry-catchblockwithinthedesigntimemethodwillneverperformduringthetestrun.TheonlyreliablewaytoaddthecatchcapabilitytothetestaspartofthetestcaseruntimeistousetheCitrustestactionwhichgetsexecutedduringtestruntime.
CitrusReferenceGuide
188Catch
![Page 189: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/189.jpg)
RunningApacheAntbuildtargets
Theactionloadsabuild.xmlAntfileandexecutesoneormoretargetsintheAntproject.ThetargetisexecutedwithoptionalbuildpropertiespassedtotheAntrun.TheAntbuildoutputisloggedwithCitrusloggerandthetestcasesuccessisboundtotheAntbuildsuccess.ThismeansincasetheAntbuildfailsforsomereasonthetestcasewillalsofailwithbuildexceptionaccordingly.
SeethisbasicAntrunexampletoseehowitworkswithinyourtestcase:
XMLDSL
<testcasename="AntRunTest"><variables><variablename="today"value="citrus:currentDate()"/></variables><actions><antbuild-file="classpath:com/consol/citrus/actions/build.xml"><executetarget="sayHello"/><properties><propertyname="date"value="$today"/><propertyname="welcomeText"value="Hello!"/></properties></ant></actions></testcase>
JavaDSLdesigner
@CitrusTestpublicvoidantRunTest()variable("today","citrus:currentDate()");
antrun("classpath:com/consol/citrus/actions/build.xml").target("sayHello").property("date","$today").property("welcomeText","$Hello!");
JavaDSLrunner
@CitrusTestpublicvoidantRunTest()variable("today","citrus:currentDate()");
CitrusReferenceGuide
189Antrun
![Page 190: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/190.jpg)
antrun(action->action.buildFilePath("classpath:com/consol/citrus/actions/build.xml").target("sayHello").property("date","$today").property("welcomeText","$Hello!"));
Therespectivebuild.xmlAntfilemustprovidethetargettocall.Forexample:
<projectname="citrus-build"default="sayHello"><propertyname="welcomeText"value="WelcometoCitrus!"></property>
<targetname="sayHello"><echomessage="$welcomeText-Todayis$date"></echo></target>
<targetname="sayGoodbye"><echomessage="Goodbyeeverybody!"></echo></target></project>
AsyoucanseeyoucanpasscustombuildpropertiestotheAntbuildexecution.ExistingAntbuildpropertiesarereplacedandyoucanusethepropertiesinyourbuildfileasusual.
Youcanalsocallmultipletargetswithinonesinglebuildrunbyusingacommaseparatedlistoftargetnames:
XMLDSL
<testcasename="AntRunTest"><variables><variablename="today"value="citrus:currentDate()"/></variables><actions><antbuild-file="classpath:com/consol/citrus/actions/build.xml"><executetargets="sayHello,sayGoodbye"/><properties><propertyname="date"value="$today"/></properties></ant></actions></testcase>
JavaDSLdesigner
CitrusReferenceGuide
190Antrun
![Page 191: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/191.jpg)
@CitrusTestpublicvoidantRunTest()variable("today","citrus:currentDate()");
antrun("classpath:com/consol/citrus/actions/build.xml").targets("sayHello","sayGoodbye").property("date","$today");
JavaDSLrunner
@CitrusTestpublicvoidantRunTest()variable("today","citrus:currentDate()");
antrun(action->action.buildFilePath("classpath:com/consol/citrus/actions/build.xml").targets("sayHello","sayGoodbye").property("date","$today"));
Thebuildpropertiescanliveinexternalfileresourceasanalternativetotheinlinepropertydefinitions.Youjusthavetousetherespectivefileresourcepathandallnestedpropertiesgetloadedasbuildproperties.
Inadditiontothatyoucanalsodefineacustombuildlistener.ThebuildlistenermustimplementtheAntAPIinterfaceorg.apache.tools.ant.BuildListener.DuringtheAntbuildrunthebuildlisteneriscalledwithseveralcallbackmethods(e.g.buildStarted(),buildFinished(),targetStarted(),targetFinished(),...).ThisishowyoucanaddadditionallogictotheAntbuildrunfromCitrus.Acustombuildlistenercouldmanagethefailstateofyourtestcase,inparticularbyraisingsomeexceptionforcingthetestcasetofailaccordingly.
XMLDSL
<testcasename="AntRunTest"><actions><antbuild-file="classpath:com/consol/citrus/actions/build.xml"build-listener="customBuildListener"><executetarget="sayHello"/><propertiesfile="classpath:com/consol/citrus/actions/build.properties"/></ant></actions></testcase>
CitrusReferenceGuide
191Antrun
![Page 192: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/192.jpg)
JavaDSLdesigner
@AutowiredprivateBuildListenercustomBuildListener;
@CitrusTestpublicvoidantRunTest()antrun("classpath:com/consol/citrus/actions/build.xml").target("sayHello").propertyFile("classpath:com/consol/citrus/actions/build.properties").listener(customBuildListener);
JavaDSLrunner
@AutowiredprivateBuildListenercustomBuildListener;
@CitrusTestpublicvoidantRunTest()antrun(action->action.buildFilePath("classpath:com/consol/citrus/actions/build.xml").target("sayHello").propertyFile("classpath:com/consol/citrus/actions/build.properties").listener(customBuildListener));
ThecustomBuildListenerusedintheexampleaboveshouldreferenceaSpringbeanintheCitrusapplicationcontext.Thebeanimplementstheinterfaceorg.apache.tools.ant.BuildListenerandcontrolstheAntbuildrun.
CitrusReferenceGuide
192Antrun
![Page 193: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/193.jpg)
Start/Stopserverinstances
Citrusisworkingwithservercomponentsthatarestartedandstoppedwithinatestrun.ThiscanbeaHttpserverorsomeSMTPmailserverforinstance.UsuallytheCitrusservercomponentsareautomaticallystartedwhenCitrusisstartingandrespectivelystoppedwhenCitrusisshuttingdown.Sometimesitmightbehelpfultoexplicitlystartandstopaserverinstancewithinyourtestcase.Hereyoucanusespecialstartandstoptestactionsinsideyourtest.Thisisagoodwaytotestdowntimescenariosofinterfacepartnerswithrespectiveerrorhandlingwhenconnectionstoserversarelost
Letmeexplainwithasimplesampletestcase:
XMLDSL
<testcasename="sleepTest"><actions><startserver="myMailServer"/>
<sleep/>
<stopserver="myMailServer"/></actions></testcase>
ThestartandstopservertestactionreceiveaservernamewhichreferencesaSpringbeancomponentoftypecom.consol.citrus.server.ServerinyourbasicSpringapplicationcontext.Theserverinstanceisstartedorstoppedwithinthetestcase.Asyoucanseeinthenextlistingwecanalsostartandstopmultipleserverinstanceswithinasingletestaction.
<testcasename="sleepTest"><actions><start><servers><servername="myMailServer"/><servername="myFtpServer"/></servers></start>
<sleep/>
<stop><servers><servername="myMailServer"/>
CitrusReferenceGuide
193Manageserver
![Page 194: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/194.jpg)
<servername="myFtpServer"/></servers></stop></actions></testcase>
WhenusingtheJavaDSLthebestwaytoreferenceaserverinstanceistoautowiretheSpringbeanviadependencyinjection.TheSpringframeworktakescaseoninjectingtheproperSpringbeancomponentdefinedintheSPringapplicationcontext.ThiswayyoucaneasilystartandstopserverinstanceswithinJavaDSLtestcases.
JavaDSLdesignerandrunner
@Autowired@Qualifier("myFtpServer")privateFtpServermyFtpServer;
@CitrusTestpublicvoidstartStopServerTest()start(myFtpServer);
sleep();
stop(myFtpServer);
NoteStartingandstoppingserverinstancesisasynchronoustestaction.Thismeansthatyourtestcaseiswaitingfortheservertostartbeforeothertestactionstakeplace.Startuptimesandshutdownofserverinstancesmaydelayyourtestaccordingly.
AsyoucanseestartingandstoppingCitrusserverinstancesisveryeasy.Youcanalsowriteyourownserverimplementationsbyimplementingtheinterfacecom.consol.citrus.server.Server.Allcustomserverimplementationscanthenbestartedandstoppedduringatestcase.
CitrusReferenceGuide
194Manageserver
![Page 195: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/195.jpg)
StopTimer
Theactioncanbeusedforstoppingeitheraspecifictimer(containers-timer)oralltimersrunningwithinatest.Thisactionisusefulwhentimersarestartedinthebackground(usingparallelorfork=true)andyouwishtostopthesetimersattheendofthetest.Someexamplesofusingthisactionareprovidedbelow:
XMLDSL
<testcasename="timerTest"><actions><timerid="forkedTimer"fork="true"><sleepmilliseconds="50"/></timer>
<timerfork="true"><sleepmilliseconds="50"/></timer>
<timerrepeatCount="5"><sleepmilliseconds="50"/></timer>
<stop-timertimerId="forkedTimer"/></actions><finally><stop-timer/></finally></testcase>
JavaDSLdesignerandrunner
@CitrusTestpublicvoidtimerTest()
timer().timerId("forkedTimer").fork(true).actions(sleep(50L));
timer().fork(true).actions(sleep(50L));
CitrusReferenceGuide
195Stoptimer
![Page 196: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/196.jpg)
timer().repeatCount(5).actions(sleep(50L));
stopTimer("forkedTimer")
doFinally().actions(stopTimer());
Intheaboveexample3timersarestarted,thefirst2inthebackgroundandthethirdinthetestexecutionthread.Timer#3hasarepeatCountsetto5soitwillterminateautomaticallyafter5runs.Timer#1and#2howeverhavenorepeatCountsetsotheywillexecuteuntiltheyaretoldtostop.
Timer#1isstoppedexplicitlyusingthefirststopTimeraction.HerethestopTimeractionincludesthenameofthetimertostop.Thisisconvenientwhenyouwishtoterminateaspecifictimer.HoweversincenotimerIdwassetfortimer#2,youcanterminatethis(andallothertimers)usingthe'stopTimer'actionwithnoexplicittimerIdset.
CitrusReferenceGuide
196Stoptimer
![Page 197: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/197.jpg)
Includingcustomtestactions
Nowwehavealookattheopportunitytoaddcustomtestactionstothetestcaseflow.Letusstartthissectionwithanexample:
XMLDSL
<testcasename="ActionReferenceTest"><actions><actionreference="cleanUpDatabase"/><actionreference="mySpecialAction"/></actions></testcase>
ThegenericelementreferencesSpringbeansthatimplementtheJavainterfacecom.consol.citrus.TestAction.ThisisaveryfastwaytoaddyourownactionimplementationstoaCitrustestcase.ThiswayyoucaneasilyimplementyourownactionsinJavaandincludethemintothetestcase.
Intheexampleabovethecalledactionsarespecialdatabasecleanupimplementations.TheactionsaredefinedasSpringbeansintheCitrusconfigurationandgetreferencedbytheirbeannameorid.
<beanid="cleanUpDatabase"class="my.domain.citrus.actions.SpecialDatabaseCleanupAction"><propertyname="dataSource"ref="testDataSource"/></bean>
TheSpringapplicationcontextholdsyourcustombeanimplementations.YoucansetpropertiesandusethefullSpringpowerwhileimplementingyourcustomtestactioninJava.LetushavealookonhowsuchaJavaclassmaylooklike.
importcom.consol.citrus.actions.AbstractTestAction;importcom.consol.citrus.context.TestContext;
publicclassSpecialDatabaseCleanupActionextendsAbstractTestAction
@AutowiredprivateDataSourcedataSource;
@OverridepublicvoiddoExecute(TestContextcontext)JdbcTemplatejdbcTemplate=newJdbcTemplate(dataSource);
CitrusReferenceGuide
197Genericaction
![Page 198: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/198.jpg)
jdbcTemplate.execute("...");
AllyouneedtodoinyourJavaclassistoimplementtheCitruscom.consol.citrus.TestActioninterface.Theabstractclasscom.consol.citrus.actions.AbstractTestActionmayhelpyoutostartwithyourcustomtestactionimplementationasitprovidesbasicmethodimplementationssoyoujusthavetoimplementthedoExecute()method.
WhenusingtheJavatestcaseDSLyouarealsoquitecomfortablewithincludingyourcustomtestactions.
JavaDSLdesignerandrunner
@AutowiredprivateSpecialDatabaseCleanupActioncleanUpDatabaseAction;
@CitrusTestpublicvoidgenericActionTest()echo("Nowlet'sincludeourspecialtestaction");
action(cleanUpDatabaseAction);
echo("That'sit!");
Usinganonymousclassimplementationsisalsopossible.
JavaDSLdesignerandrunner
@CitrusTestpublicvoidgenericActionTest()echo("Nowlet'scallourspecialtestactionanonymously");
action(newAbstractTestAction()publicvoiddoExecute(TestContextcontext)//dosomething);
echo("That'sit!");
CitrusReferenceGuide
198Genericaction
![Page 199: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/199.jpg)
CitrusReferenceGuide
199Genericaction
![Page 200: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/200.jpg)
TemplatesTemplatesgroupactionsequencestoalogicalunit.Youcanthinkoftemplatesasreusablecomponentsthatareusedinseveraltests.Themaintenanceismuchmoreeffectivebecausethetemplatesarereferencedseveraltimes.
Thetemplatealwayshasauniquename.Insideatestcasewecallthetemplatebythisuniquename.Havealookatafirstexample:
<templatename="doCreateVariables"><create-variables><variablename="var"value="123456789"/></create-variables>
<call-templatename="doTraceVariables"/></template>
<templatename="doTraceVariables"><echo><message>Currenttimeis:$time</message></echo>
<trace-variables/></template>
Thecodeexampleabovedescribestwotemplatedefinitions.Templatesholdasequenceoftestactionsorcallothertemplatesthemselvesasseenintheexampleabove.
NoteTheactioncallsothertemplatesbytheirname.ThecalledtemplatenotnecessarilyhastobelocatedinthesametestcaseXMLfile.ThetemplatemightbedefinedinaseparateXMLfileotherthanthetestcaseitself:
XMLDSL
<testcasename="templateTest"><variables><variablename="myTime"value="citrus:currentDate()"/></variables><actions><call-templatename="doCreateVariables"/>
<call-templatename="doTraceVariables"><parametername="time"value="$myTime">
CitrusReferenceGuide
200Templates
![Page 201: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/201.jpg)
</call-template></actions></testcase>
JavaDSLdesigner
@CitrusTestpublicvoidtemplateTest()variable("myTime","citrus:currentDate()");
applyTemplate("doCreateVariables");
applyTemplate("doTraceVariables").parameter("time","$myTime");
JavaDSLrunner
@CitrusTestpublicvoidtemplateTest()variable("myTime","citrus:currentDate()");
applyTemplate(template->template.name("doCreateVariables"));
applyTemplate(template->template.name("doTraceVariables").parameter("time","$myTime"));
Thereisanopenquestionwhendealingwithtemplatesthataredefinedsomewhereelseoutsidethetestcase.Howtohandlevariables?Atemplatesmayusedifferentvariablenamesthenthetestandviceversa.Nodoubtthetemplatewillfailassoonasspecialvariableswithrespectivevaluesarenotpresent.Unknownvariablescausethetemplateandthewholetesttofailwitherrors.
Soafirstapproachwouldbetoharmonizevariableusageacrosstemplatesandtestcases,sothattemplatesandtestcasesdousethesamevariablenaming.Butthisapproachmightleadtohighcalibrationeffort.Thereforetemplatessupportparameterstosolvethisproblem.Whenatemplateiscalledthecallingactorisabletosetsomeparameters.Letusdiscussanexampleforthisissue.
Thetemplate"doDateCoversion"inthenextsampleusesthevariable$date.Thecallingtestcasecansetthisvariableasaparameterwithoutactuallydeclaringthevariableinthetestitself:
CitrusReferenceGuide
201Templates
![Page 202: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/202.jpg)
<call-templatename="doDateCoversion"><parametername="date"value="$sampleDate"></call-template>
ThevariablesampleDateisalreadypresentinthetestcaseandgetstranslatedintothedateparameter.Followingfromthatthetemplateworksfinealthoughtestandtemplatedoworkondifferentvariablenamings.
Withtemplateparametersyouareabletosolvethecalibrationeffortwhenworkingwithtemplatesandvariables.Itisalwaysagoodideatochecktheusedvariables/parametersinsideatemplatewhencallingit.Theremightbeavariablethatisnotdeclaredyetinsideyourtest.Soyouneedtodefinethisvalueasaparameter.
TemplateparametersmaycontainmorecomplexvalueslikeXMLfragments.Thecall-templateactionoffersfollowingCDATAvariationfordefiningcomplexparametervalues:
<call-templatename="printXMLPayload"><parametername="payload"><value><![CDATA[<HelloRequestxmlns="http://www.consol.de/schemas/samples/sayHello.xsd"><Text>HelloSouth$var</Text></HelloRequest>]]></value></parameter></call-template>
ImportantWhenatemplateworksonvariablevaluesandparameterschangestothesevariableswillautomaticallyaffectthevariablesinthewholetest.Soifyouchangeavariable'svalueinsideatemplateandthevariableisdefinedinsidethetestcasethechangeswillaffectthevariableinaglobalcontext.Wehavetobecarefulwiththiswhenexecutingatemplateseveraltimesinatest,especiallyincombinationwithparallelcontainers(seecontainers-parallel).
<parallel><call-templatename="print"><parametername="param1"value="1"/><parametername="param2"value="HelloEurope"/></call-template><call-templatename="print"><parametername="param1"value="2"/><parametername="param2"value="HelloAsia"/></call-template>
CitrusReferenceGuide
202Templates
![Page 203: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/203.jpg)
<call-templatename="print"><parametername="param1"value="3"/><parametername="param2"value="HelloAfrica"/></call-template></parallel>
Inthelistingaboveatemplateprintiscalledseveraltimesinaparallelcontainer.Theparametervalueswillbehandledinaglobalcontext,soitisquitelikelytohappenthatthetemplateinstancesinfluenceeachotherduringexecution.Wemightgetsuchprintmessages:
2.HelloEurope2.HelloAfrica3.HelloAfrica
Indexparametersdonotfitandthemessage'HelloAsia'iscompletelygone.Thisisbecausetemplatesoverwriteparameterstoeachotherastheyareexecutedinparallelatthesametime.Toavoidthisbehaviorweneedtotellthetemplatethatitshouldhandleparametersaswellasvariablesinalocalcontext.Thiswillenforcethateachtemplateinstanceisworkingonadedicatedlocalcontext.Seetheglobal-contextattributethatissettofalseinthisexample:
<templatename="print"global-context="false"><echo><message>$param1.$param2</message></echo></template>
Afterthattemplateinstanceswon'tinfluenceeachotheranymore.Butnoticethatvariablechangesinsidethetemplatethendonotaffectthetestcaseneither.
CitrusReferenceGuide
203Templates
![Page 204: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/204.jpg)
TestbehaviorsTestbehaviorscombineactionsequencestoalogicalunit.ThebehaviordefinesasetoftestactionsthatcanbeappliedtoaJavaDSLtestcase.Followingfromthatyoucansaythatbehaviorsarereusabletestactiontemplates.Themaintenanceismuchmoreeffectivewhenyoureusebasictestactionsinmanytestcases.
ThebehaviorisaseparateJavaDSLclasswithasingleapplymethodthatconfiguresthetestactions.Havealookatthisfirstexample:
JavaDSL
publicclassFooBehaviorextendsAbstractTestBehaviorpublicvoidapply()variable("foo","test");
echo("fooBehavior");
publicclassBarBehaviorextendsAbstractTestBehaviorpublicvoidapply()variable("bar","test");
echo("barBehavior");
AsyoucanseethebehaviorclassisabletousetheCitrusJavaDSLasusual.Eachbehaviorisabletodefinetestvariablesandactions.Inatestcaseyoucanapplythebehaviorsasfollows:
JavaDSL
@CitrusTestpublicvoidbehaviorTest()variable("myTime","citrus:currentDate()");
FooBehaviorfooBehavior=newFooBehavior();applyBehavior(fooBehavior);
applyBehavior(newBarBehavior());
applyBehavior(fooBehavior);
CitrusReferenceGuide
204Testbehaviors
![Page 205: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/205.jpg)
Whendealingwithbehaviorstestactionsaredefinedsomewhereoutsidethetestcase.Howdowehandletestvariables?Abehaviormayusedifferentvariablenamesthenthetestandviceversa.Nodoubtthebehaviorwillfailassoonasspecialvariableswithrespectivevaluesarenotpresent.Unknownvariablescausethebehaviorandthewholetesttofailwitherrors.
Soagoodapproachwouldbetoharmonizevariableusageacrossbehaviorsandtestcases,sothattemplatesandtestcasesdousethesamevariablenaming.Thebehaviorautomaticallyknowsallvariablesinthetestcase.Andalltestvariablescreatedinsidethebehaviorarevisibletothetestcaseafterapplying.
ImportantWhenabehaviorchangesvariablesthiswillautomaticallyaffectthevariablesinthewholetest.Soifyouchangeavariable'svalueinsideabehaviorandthevariableisdefinedinsidethetestcasethechangeswillaffectthevariableinaglobaltestcontext.Thismeanswehavetobecarefulwhenexecutingabehaviorseveraltimesinatest,especiallyincombinationwithparallelcontainers(seecontainers-parallel).
Behaviortypes
ThetestcaseinJavaisabletofolloweitherdesignerorrunnerstrategies.Thismeanswealsohavetwodifferentbehaviortypesfordesignerandrunnerrespectively.Thebehaviorsarelocatedinseparatepackages
com.consol.citrus.dsl.design.AbstractTestBehaviorcom.consol.citrus.dsl.runner.AbstractTestBehavior
Decidewhichbasebehavioryouwanttoextendfromaccordingtoyourtestcasenature.
CitrusReferenceGuide
205Testbehaviors
![Page 206: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/206.jpg)
ContainersSimilartotemplatesacontainerelementholdsonetomanytestactions.Incontrasttothetemplatethecontainerappearsdirectlyinsidethetestcaseactionchain,meaningthatthecontainerisnotreferencedbymorethanonetestcase.
Containersexecutetheembeddedtestactionsinspecificlogic.Thiscanbeanexecutioniniterationforinstance.Combinedifferentcontainerswitheachotherandyouwillbeabletogenerateverypowerfulhierarchicalstructuresinordertocreateacomplexexecutionlogic.Inthefollowingsectionssomepredefinedcontainersaredescribed.
CitrusReferenceGuide
206Containers
![Page 207: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/207.jpg)
Sequential
Thesequentialcontainerexecutestheembeddedtestactionsinstrictsequence.Readersnowmightsearchforthedifferencetothenormalactionchainthatisspecifiedinsidethetestcase.Theactualpowerofsequentialcontainersdoesshowonlyincombinationwithothercontainerslikeiterationsandparallels.Wewillseethislaterwhenhandlingthesecontainers.
Fornowthesequentialcontainerseemsnotverysensational-onemightsayboring-becauseitsimplygroupsapairoftestactionstosequentialexecution.
XMLDSL
<testcasename="sequentialTest"><actions><sequential><trace-time/><sleep/><echo><message>HalloTestFramework</message></echo><trace-time/></sequential></actions></testcase>
JavaDSLdesignerandrunner
@CitrusTestpublicvoidsequentialTest()sequential().actions(stopTime(),sleep(1.0),echo("HelloCitrus"),stopTime());
CitrusReferenceGuide
207Sequential
![Page 208: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/208.jpg)
Conditional
Nowwedealwithconditionalexecutionsoftestactions.Nestedactionsinsideaconditionalcontainerareexecutedonlyincaseabooleandexpressionevaluatestotrue.Otherwisethecontainerexecutionisnotperformedatall.
Seesomeexampletofindouthowitworkswiththeconditionalexpressionstring.
XMLDSL
<testcasename="conditionalTest"><variables><variablename="index"value="5"/><variablename="shouldSleep"value="true"/></variables>
<actions><conditionalexpression="$index=5"><sleepseconds="10"/></conditional>
<conditionalexpression="$shouldSleep"><sleepseconds="10"/></conditional>
<conditionalexpression="@assertThat('$shouldSleep','anyOf(is(true),isEmptyString())')@"<sleepseconds="10"/></conditional></actions></testcase>
JavaDSLdesignerandrunner
@CitrusTestpublicvoidconditionalTest()variable("index",5);variable("shouldSleep",true);
conditional().when("$index=5")).actions(sleep(10000L));
conditional().when("$shouldSleep")).actions(sleep(10000L)
CitrusReferenceGuide
208Conditional
![Page 209: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/209.jpg)
);
conditional().when("$shouldSleep",anyOf(is("true"),isEmptyString())).actions(sleep(10000L));
Thenestedsleepactionisexecutedincasethevariable$indexisequaltothevalue'5'.Thisconditionalexecutionoftestactionsisusefulwhendealingwithdifferenttestenvironmentssuchasdifferentoperatingsystemsforinstance.Theconditionalcontaineralsosupportsexpressionsthatevaluatetothecharactersequence"true"or"false"asshowninthe$shouldSleepexample.
ThelastconditionalcontainerintheexampleabovemakesuseofHamcrestmatchers.Thematcherevaluatestotrueoffalseandbasedonthatthecontaineractionsareexecutedorskipped.TheHamcrestmatchersareverypowerfulwhenitcomestoevaluationofmultipleconditionsatatime.
CitrusReferenceGuide
209Conditional
![Page 210: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/210.jpg)
Parallel
Parallelcontainersexecutetheembeddedtestactionsconcurrenttoeachother.EveryactioninthiscontainerwillbeexecutedinaseparateJavaThread.Followingexampleshouldclarifytheusage:
XMLDSL
<testcasename="parallelTest"><actions><parallel><sleep/>
<sequential><sleep/><echo><message>1</message></echo></sequential>
<echo><message>2</message></echo>
<echo><message>3</message></echo>
<iteratecondition="ilt=5"index="i"><echo><message>10</message></echo></iterate></parallel></actions></testcase>
JavaDSLdesignerandrunner
@CitrusTestpublicvoidparalletTest()parallel().actions(sleep(),sequential().actions(sleep(),echo("1")
CitrusReferenceGuide
210Parallel
![Page 211: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/211.jpg)
),echo("2"),echo("3"),iterate().condition("ilt=5").index("i")).actions(echo("10")));
Sothenormaltestactionprocessingwouldbetoexecuteoneactionafteranother.Asthefirstactionisasleepoffiveseconds,thewholetestprocessingwouldstopandwaitfor5seconds.Thingsaredifferentinsidetheparallelcontainer.Herethedescendingtestactionswillnotwaitbutexecuteatthesametime.
NoteNotethatcontainerscaneasilywrapothercontainers.Theexampleshowsasimplecombinationofsequentialandparallelcontainersthatwillarchiveacomplexexecutionlogic.Actionsinsidethesequentialcontainerwillexecuteoneafteranother.Butactionsinparallelwillbeexecutedatthesametime.
CitrusReferenceGuide
211Parallel
![Page 212: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/212.jpg)
Iterate
Iterationsareverypowerfulelementswhendescribingcomplexlogic.Thecontainerexecutestheembeddedactionsseveraltimes.Thecontainerwillcontinuewithloopingaslongasthedefinedbreakingconditionstringevaluatestotrue.Incasetheconditionevaluatestofalsetheiterationwillbreakanfinishexecution.
XMLDSL
<testcasename="iterateTest"><actions><iterateindex="i"condition="ilt5"><echo><message>indexis:$i</message></echo></iterate></actions></testcase>
JavaDSLdesignerandrunner
@CitrusTestpublicvoiditerateTest()iterate().condition("ilt5").index("i")).actions(echo("indexis:$i"));
Theattribute"index"automaticallydefinesanewvariablethatholdstheactualloopindexstartingat"1".Thisindexvariableisavailableasanormalvariableinsidetheiteratecontainer.Thereforeitispossibletoprintouttheactualloopindexintheechoactionasshownintheaboveexample.
Theconditionstringismandatoryanddescribestheactualendoftheloop.Initeratecontainerstheloopwillbreakincasetheconditionevaluatestofalse.
TheconditionstringcanbeanyBooleanexpressionandsupportsseveraloperators:
lt(lowerthan)
lt=(lowerthanequals)
gt(greaterthan)
CitrusReferenceGuide
212Iterate
![Page 213: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/213.jpg)
gt=(greaterthanequals)
=(equals)
and(logicalcombiningoftwoBooleanvalues)
or(logicalcombiningoftwoBooleanvalues)
()(brackets)
ImportantItisveryimportanttonoticethattheconditionisevaluatedbeforetheveryfirstiterationtakesplace.Theloopthereforecanbeexecuted0-ntimesaccordingtotheconditionvalue.
Nowthebooleanexpressionevaluationasdescribedaboveislimitedtoverybasicoperationsuchaslowerthan,greaterthanandsoon.WealsocanuseHamcrestmatchersinconditionsthatarewaymorepowerfulthanthat.
XMLDSL
<testcasename="iterateTest"><actions><iterateindex="i"condition="@assertThat(lessThan(5))@"><echo><message>indexis:$i</message></echo></iterate></actions></testcase>
JavaDSLdesignerandrunner
@CitrusTestpublicvoiditerateTest()iterate().condition(lessThan(5)).index("i")).actions(echo("indexis:$i"));
IntheexampleaboveweuseHamcrestmatchersascondition.YoucancombineHamcrestmatchersandcreateverypowerfulconditionevaluationshere.
CitrusReferenceGuide
213Iterate
![Page 214: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/214.jpg)
CitrusReferenceGuide
214Iterate
![Page 215: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/215.jpg)
Repeatuntiltrue
Quitesimilartothepreviouslydescribediteratecontainerthisrepeatingcontainerwillexecuteitsactionsinaloopaccordingtoanendingcondition.TheconditiondescribesaBooleanexpressionusingtheoperatorsasdescribedinthepreviouschapter.
NoteTheloopcontinuesitsworkuntiltheprovidedconditionevaluatestotrue.Itisveryimportanttonoticethattherepeatloopwillexecutetheactionsbeforeevaluatingthecondition.Thismeanstheactionsgetexecuted1-ntimes.
XMLDSL
<testcasename="iterateTest"><actions><repeat-until-trueindex="i"condition="(i=3)or(i=5)"><echo><message>indexis:$i</message></echo></repeat-until-true></actions></testcase>
JavaDSLdesignerandrunner
@CitrusTestpublicvoidrepeatTest()repeat().until("(igt5)or(i=3)").index("i")).actions(echo("indexis:$i"));
Asyoucanseetherepeatcontainerisonlyexecutedwhentheiteratingconditionexpressionevaluatestofalse.Bythetimetheconditionistrueexecutionisdiscontinued.Youcanusebasiclogicaloperatorssuchasand,orandsoon.
AmorepowerfulwayisgivenbyHamcrestmatchersthataredirectlysupportedinconditionexpressions.
XMLDSL
<testcasename="iterateTest"><actions>
CitrusReferenceGuide
215Repeat
![Page 216: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/216.jpg)
<repeat-until-trueindex="i"condition="@assertThat(anyOf(is(3),is(5))@"><echo><message>indexis:$i</message></echo></repeat-until-true></actions></testcase>
JavaDSLdesignerandrunner
@CitrusTestpublicvoidrepeatTest()repeat().until(anyOf(is(3),is(5)).index("i")).actions(echo("indexis:$i"));
TheHamcrestmatcherusagesimplifiesthereadingalot.Anditempowersyoutocombinemorecomplexconditionexpressions.SoIpersonallypreferthissyntax.
CitrusReferenceGuide
216Repeat
![Page 217: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/217.jpg)
Repeatonerroruntiltrue
Thenextloopingcontaineriscalledrepeat-on-error-until-true.Thiscontainerrepeatsagroupofactionsincaseoneembeddedactionfailedwitherror.Incaseofanerrorinsidethecontainertheloopwilltrytoexecuteallembeddedactionsagaininordertoseekforoverallsuccess.Theexecutioncontinuesuntilallembeddedactionswereprocessedsuccessfullyortheendingconditionevaluatestotrueandtheerror-loopwillleadtofinalfailure.
XMLDSL
<testcasename="iterateTest"><actions><repeat-onerror-until-trueindex="i"condition="i=5"><echo><message>indexis:$i</message></echo><fail/></repeat-onerror-until-true></actions></testcase>
JavaDSLdesigner
@CitrusTestpublicvoidrepeatOnErrorTest()repeatOnError(echo("indexis:$i"),fail("Forcelooptofail!")).until("i=5").index("i");
JavaDSLrunner
@CitrusTestpublicvoidrepeatOnErrorTest()repeatOnError().until("i=5").index("i")).actions(echo("indexis:$i"),fail("Forcelooptofail!"));
CitrusReferenceGuide
217RepeatOnError
![Page 218: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/218.jpg)
Inthecodeexampletheerror-loopcontinuesfourtimesastheactiondefinitelyfailsthetest.DuringthefifthiterationThecondition"i=5"evaluatestotrueandtheloopbreaksitsprocessingleadingtoafinalfailureasthetestactionswerenotsuccessful.
NoteTheoverallsuccessofthetestcasedependsontheerrorsituationinsidetherepeat-onerror-until-truecontainer.Incasetheloopbreaksbecauseoffailingactionsandtheloopwilldiscontinueitsworkthewholetestcaseisfailingtoo.Theerrorloopprocessingissuccessfulincaseallembeddedactionswerenotraisinganyerrorsduringaniteration.
Therepeat-on-errorcontaineralsooffersanautomaticsleepmechanism.Thisauto-sleeppropertywillforcethecontainertowaitagivenamountoftimebeforeexecutingthenextiteration.Weusedthismechanismalotwhenvalidatingdatabaseentries.Let'ssaywewanttochecktheexistenceofanorderentryinthedatabase.Unfortunatelythesystemundertestisnotverywellperformingandmayneedsometimetostoretheneworder.Thisamountoftimeisnotpredictable,especiallywhendealingwithdifferenthardwareonourtestenvironments(localtestingvs.servertesting).Followingfromthatourtestcasemayfailunpredictableonlybecauseofruntimeconditions.
Wecanavoidunstabletestcasesthatarebasedontheseruntimeconditionswiththeauto-sleepfunctionality.
XMLDSL
<repeat-onerror-until-trueauto-sleep="1000"condition="i=5"index="i"><echo><sqldatasource="testDataSource"><statement>SELECTCOUNT(1)ASCNT_ORDERSFROMORDERSWHERECUSTOMER_ID='$customerId'</statement><validatecolumn="CNT_ORDERS"value="1"/></sql></echo></repeat-onerror-until-true>
JavaDSLdesignerandrunner
@CitrusTestpublicvoidrepeatOnErrorTest()repeatOnError().until("i=5").index("i").autoSleep(1000)).actions(query(action->action.dataSource(testDataSource)
CitrusReferenceGuide
218RepeatOnError
![Page 219: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/219.jpg)
.statement("SELECTCOUNT(1)ASCNT_ORDERSFROMORDERSWHERECUSTOMER_ID='$customerId'".validate("CNT_ORDERS","1")));
Wesurroundedthedatabasecheckwitharepeat-onerrorcontainerhavingtheauto-sleeppropertysetto1000milliseconds.Therepeatcontainerwilltrytocheckthedatabaseuptofivetimeswithanautomaticsleepof1secondbeforeeveryiteration.Thisgivesthesystemundertestuptofivesecondstimetostorethenewentrytothedatabase.Thetestcaseisverystableandjustfitstothehardwareenvironment.Onslowtestenvironmentsthetestmayneedseveraliterationstosuccessfullyreadthedatabaseentry.Onveryfastenvironmentsthetestmaysucceedrightonthefirsttry.
ImportantWechangedautosleeptimefromsecondstomillisecondswithCitrus2.0release.SoifyouarecomingfrompreviousCitrusversionsbesuretonowusepropermillisecondvalues.
Sofastenvironmentsarenotsloweddownbystaticsleepoperationsandslowerenvironmentsarestillabletoexecutethistestcasewithhighstability.
CitrusReferenceGuide
219RepeatOnError
![Page 220: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/220.jpg)
Timer
Timersareveryusefulcontainerswhenyouwishtoexecuteacollectionoftestactionsseveraltimesatregularintervals.Thetimercomponentgeneratesaneventwhichinturntriggerstheexecutionofthenestedtestactionsassociatedwithtimer.ThiscanbeusefulinanumberoftestscenariosforexamplewhenCitrusneedstosimulateaheartbeatorifyouaredebuggingatestandyouwisttoquerythecontentsofthedatabase,tomentionjustafew.Thefollowingcodesampleshoulddemonstratethepowerandflexibilityoftimers:
XMLDSL
<testcasename="timerTest"><actions><timerid="forkedTimer"interval="100"fork="true"><echo><message>I'mgoingtoruninthebackgroundandletsomeothertestactionsrun(nestedactionrun$forkedTimer-indextimes)</echo><sleepmilliseconds="50"/></timer>
<timerrepeatCount="3"interval="100"delay="50"><sleepmilliseconds="50"/><echo><message>I'mgoingtorepeatthismessage3timesbeforethenexttestactionsareexecuted</echo></timer>
<echo><message>Testalmostcomplete.Makesurealltimersrunninginthebackgroundarestopped</echo></actions><finally><stop-timertimerId="forkedTimer"/></finally></testcase>
JavaDSLdesignerandrunner
@CitrusTestpublicvoidtimerTest()
timer().timerId("forkedTimer")
CitrusReferenceGuide
220Timer
![Page 221: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/221.jpg)
.interval(100L).fork(true).actions(echo("I'mgoingtoruninthebackgroundandletsomeothertestactionsrun(nestedactionrun$forkedTimer-indextimes)"sleep(50L));
timer().repeatCount(3).interval(100L).delay(50L).actions(sleep(50L),echo("I'mgoingtorepeatthismessage3timesbeforethenexttestactionsareexecuted");
echo("Testalmostcomplete.Makesurealltimersrunninginthebackgroundarestopped");
doFinally().actions(stopTimer("forkedTimer"));
Intheaboveexamplethefirsttimer(timerId=forkedTimer)isstartedinthebackground.Bydefaulttimersareruninthecurrentthreadofexecutionbuttostartitinthebackgroundjustuse"fork=true".Every100millisecondsthistimeremitsaneventwhichwillresultinthenestedactionsbeingexecuted.Thenested'echo'actionoutputsthenumberoftimesthistimerhasalreadybeenexecuted.Itdoesthiswiththehelpofan'index'variable,inthisexample$forkedTimer-index,whichisnamedaccordingtothetimeridwiththesuffix'-index'.Nolimitissetonthenumberoftimesthistimershouldrunsoitwillkeeponrunninguntileitheranestedtestactionfailsoritisinstructedtostop(moreonthisbelow).
Thesecondtimerisconfiguredtorun3timeswithadelayof100millisecondsbetweeneachiteration.Usingtheattribute'delay'wecangetthetimerpausefor50millisecondsbeforerunningthenestedactionsforthefirsttime.Thetimerisconfiguredtoruninthecurrentthreadofexecutionsothelasttestaction,the'echo',hastowaitforthistimertocompletebeforeitisexecuted.
Sohowdowetelltheforkedtimertostoprunning?Ifweforgettodothisthetimerwilljustexecuteindefinitely.Tohelpusoutherewecanusethe'stop-timer'action.Byaddingthistothefinallyblockweensurethatthetimerwillbestopped,evenifsome
CitrusReferenceGuide
221Timer
![Page 222: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/222.jpg)
nestedtestactionfails.Wecouldhaveeasilyaddeditasanestedtestaction,totheforkedTimerforexample,butifsomeothertestactionfailedbeforethestop-timerwascalled,thetimerwouldneverstop.
NoteYoucanalsoconfiguretimerstoruninthebackgroundusingthe'parallel'container,ratherthansettingtheattribute'fork'totrue.Usingparallelallowsmorefine-grainedcontrolofthetestandhastheaddedadvantagethatallerrorsgeneratedfromanestertimeractionarevisibletothetestexecuter.Ifanerroroccurswithinthetimerthentheteststatusissettofailed.Usingfork=trueanerrorcausesthetimertostopexecuting,buttheteststatusisnotinfluencedbythiserror.
CitrusReferenceGuide
222Timer
![Page 223: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/223.jpg)
Customcontainers
IncaseyouhaveacustomactioncontainerimplementationyoumightalsowanttouseitinJavaDSL.TheactioncontainersarehandledwithspecialcareintheJavaDSLbecausetheyhavenestedactions.SowhenyoucallatestactioncontainerintheJavaDSLyoualwayshavesomethinglikethis:
JavaDSLdesignerandrunner
@CitrusTestpublicvoidcontainerTest()echo("Thisechoisoutsideoftheactioncontainer");
sequential().actions(echo("Inside"),echo("Insideoncemore"),echo("Andagain:Inside!"));
echo("Thisechoisoutsideoftheactioncontainer");
NowthethreenestedactionsareaddedtotheactionsequentialcontainerratherthantothetestcaseitselfalthoughweareusingthesameactionJavaDSLmethodsasoutsidethecontainer.ThismechanismisonlyworkingbecauseCitrusishandlingtestactioncontainerswithspecialcare.
Acustomtestactioncontainerimplementationcouldlooklikethis:
publicclassReverseActionContainerextendsAbstractActionContainer@OverridepublicvoiddoExecute(TestContextcontext)for(inti=getActions().size();i>0;i--)getActions().get(i-1).execute(context);
Thecontainerlogicisverysimple:Thecontainerexecutesthenestedactionsinreverseorder.AsalreadymentionedCitrusneedstotakespecialcareonallactioncontainerswhenexecutingaJavaDSLtest.Thisiswhyyoushouldnotexecuteacustomtestcontainerimplementationonyourown.
CitrusReferenceGuide
223Custom
![Page 224: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/224.jpg)
@CitrusTestpublicvoidcontainerTest()ReverseActionContainerreverseContainer=newReverseActionContainer();reverseContainer.addTestAction(newEchoAction().setMessage("Foo"));reverseContainer.addTestAction(newEchoAction().setMessage("Bar"));run(reverseContainer);
TheabovecustomcontainerexecutionisgoingtofailwithinternalerrorastheCitrusJavaDSLwasnotabletorecognisetheactioncontainerasitshouldbe.AlsotheEchoActioninstancecreationisnotverycomfortable.InsteadyoucanuseaspecialcontainerJavaDSLsyntaxalsowithyourcustomcontainerimplementation:
@CitrusTestpublicvoidcontainerTest()container(newReverseActionContainer()).actions(echo("Foo"),echo("Bar"));
Thecustomcontainerimplementationnowworksfinewiththeautomaticallynestedechoactions.AndweareabletousetheusualJavaDSLsyntacticsugarfortestactionslikeecho.
Inanextstepweaddacustomsuperclassforallourtestclasseswhichprovidesahelpermethodforthecustomcontainerimplementationinordertohaveaevenmorecomfortablesyntax.
JavaDSLdesignerandrunner
publicclassCustomCitrusBaseTestextendsTestNGCitrusTestDesigner
publicAbstractTestContainerBuilder<ReverseActionContainer>reverse()returncontainer(newReverseActionContainer());
Nowallsubclassescanusethenewreversemethodforcallingthecustomcontainerimplementation.
@CitrusTestpublicvoidcontainerTest()
CitrusReferenceGuide
224Custom
![Page 225: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/225.jpg)
reverse().actions(echo("Foo"),echo("Bar"));
Nice!ThisishowweshouldintegratecustomizedtestactioncontainerstotheCitrusJavaDSL.
CitrusReferenceGuide
225Custom
![Page 226: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/226.jpg)
FinallysectionThischapterdealswithaspecialsectioninsidethetestcasethatisexecutedevenincaseerrorsdidoccurduringthetest.LetssayyouhavestartedaJettywebserverinstanceatthebeginningofthetestcaseandyouneedtoshutdowntheserverwhenthetesthasfinisheditswork.Orasasecondexampleimaginethatyouhavepreparedsomedatainsidethedatabaseatthebeginningofyourtestandyouwanttomakesurethatthedataiscleanedupattheendofthetestcase.
Inbothsituationswemightrunintosomeproblemswhenthetestfailed.Wefacetheproblemthatthewholetestcasewillterminateimmediatelyincaseoferrors.Cleanuptasksattheendofthetestactionchainmaynotbeexecutedcorrectly.
Dirtystatesinsidethedatabaseorstillrunningserverinstancesthenmightcauseproblemsforfollowingtestcases.Toavoidthisproblemsyoushouldusethefinallyblockofthetestcase.Thesectioncontainsactionsthatareexecutedevenincasethetestfails.Usingthisstrategythedatabasecleaningtasksmentionedbeforewillfindexecutionineverycase(successorfailure).
Thefollowingexampleshowshowtousethefinallysectionattheendofatest:
XMLDSL
<testcasename="finallyTest"><variables><variablename="orderId"value="citrus:randomNumber(5)"/><variablename="date"value="citrus:currentDate('dd.MM.yyyy')"/></variables><actions><sqldatasource="testDataSource"><statement>INSERTINTOORDERSVALUES($orderId,1,1,'$date')</statement></sql>
<echo><message>ORDERcreationtime:$date</message></echo></actions><finally><sqldatasource="testDataSource"><statement>
CitrusReferenceGuide
226Finally
![Page 227: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/227.jpg)
DELETEFROMORDERSWHEREORDER_ID='$orderId'</statement></sql></finally></testcase>
IntheexamplethefirstactioncreatesanentryinthedatabaseusinganINSERTstatement.Tobesurethattheentryinthedatabaseisdeletedafterthetest,thefinallysectioncontainstherespectiveDELETEstatementthatisalwaysexecutedregardlessthetestcasestate(successfulorfailed).
OfcourseyoucanalsousethefinallyblockintheJavatestcaseDSL.Findfollowingexampletoseehowitworks:
JavaDSLdesigner
@CitrusTestpublicvoidfinallySectionTest()variable("orderId","citrus:randomNumber(5)");variable("date","citrus:currentDate('dd.MM.yyyy')");
sql(dataSource).statement("INSERTINTOORDERSVALUES($orderId,1,1,'$date')");
echo("ORDERcreationtime:citrus:currentDate('dd.MM.yyyy')");
doFinally(sql(dataSource).statement("DELETEFROMORDERSWHEREORDER_ID='$orderId'"));
JavaDSLrunner
@CitrusTestpublicvoidfinallySectionTest()variable("orderId","citrus:randomNumber(5)");variable("date","citrus:currentDate('dd.MM.yyyy')");
sql(action->action.dataSource(dataSource).statement("INSERTINTOORDERSVALUES($orderId,1,1,'$date')"));
echo("ORDERcreationtime:citrus:currentDate('dd.MM.yyyy')");
doFinally().actions(sql(action->action.dataSource(dataSource).statement("DELETEFROMORDERSWHEREORDER_ID='$orderId'");
CitrusReferenceGuide
227Finally
![Page 228: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/228.jpg)
NoteJavadevelopersmightaskwhynotusetry-finallyJavablockinstead?Theanswerissimpleyetveryimportanttounderstand.The@CitrusTestannotatedmethodiscalledatdesigntimeofthetestcase.Themethodbuildsthetestcaseafterwardsthetestisexecutedatruntime.Thismeansthatatry-finallyblockwithinthe@CitrusTestannotatedmethodwillneverperformduringthetestrunbutatdesigntimebeforethetestgetsexecuted.ThisiswhywehavetoaddthefinallysectionaspartofthetestcasewithdoFinally().
CitrusReferenceGuide
228Finally
![Page 229: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/229.jpg)
JMSsupportCitrusprovidessupportforsendingandreceivingJMSmessages.Wehavetoseparatebetweensynchronousandasynchronouscommunication.SointhischapterweexplainhowtosetupJMSmessageendpointsforsynchronousandasynchronousoutboundandinboundcommunication
NoteTheJMScomponentsinCitrusarekeptinaseparateMavenmodule.IfnotalreadydonesoyouhavetoincludethemoduleasMavendependencytoyourproject
<dependency><groupId>com.consol.citrus</groupId><artifactId>citrus-jms</artifactId><version>2.7.1</version></dependency>
Citrusprovidesa"citrus-jms"configurationnamespaceandschemadefinitionforJMSrelatedcomponentsandfeatures.IncludethisnamespaceintoyourSpringconfigurationinordertousetheCitrusJMSconfigurationelements.ThenamespaceURIandschemalocationareaddedtotheSpringconfigurationXMLfileasfollows.
<beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:citrus-jms="http://www.citrusframework.org/schema/jms/config"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.citrusframework.org/schema/jms/confighttp://www.citrusframework.org/schema/jms/config/citrus-jms-config.xsd">
[...]
</beans>
AfterthatyouareabletousecustomizedCitrusXMLelementsinordertodefinetheSpringbeans.
JMSendpoints
CitrusReferenceGuide
229Jms
![Page 230: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/230.jpg)
BydefaultCitrusJMSendpointsareasynchronous.Soletusfirstofalldealwithasynchronousmessagingwhichmeansthatwewillnotwaitforanyresponsemessageaftersendingorreceivingamessage.
ThetestcaseitselfshouldnotknowaboutJMStransportdetailslikequeuenamesorconnectioncredentials.ThisinformationisstoredintheendpointcomponentconfigurationthatlivesinthebasicSpringconfigurationfileinCitrus.SoletushavealookatasimpleJMSmessageendpointconfigurationinCitrus.
<citrus-jms:endpointid="helloServiceQueueEndpoint"destination-name="Citrus.HelloService.Request.Queue"timeout="10000"/>
TheendpointcomponentreceivesanuniqueidandaJMSdestinationname.Thiscanbeaqueueortopicdestination.WewilldealwithJMStopicslateron.FornowthetimeoutsettingcompletesourfirstJMSendpointcomponentdefinition.
TheendpointneedsaJMSconnectionfactoryforconnectingtoaJMSmessagebroker.TheconnectionfactoryisalsoaddedasSpringbeantotheCitrusSpringapplicationcontext.
<beanid="connectionFactory"class="org.apache.activemq.ActiveMQConnectionFactory"><propertyname="brokerURL"value="tcp://localhost:61616"/></bean>
TheJMSconnectionfactoryreceivestheJMSmessagebrokerURLandisabletoholdmanyotherconnectionspecificoptions.InthisexampleweusetheApacheActiveMQconnectionfactoryimplementationaswewanttousetheActiveMQmessagebroker.CitrusworksbydefaultwithabeanidconnectionFactory.AllCitrusJMScomponentwillautomaticallyrecognizethisconnectionfactory.
TipSpringmakesitveryeasytoconnecttootherJMSbrokerimplementationstoo(e.g.ApacheActiveMQ,TIBCOEnterpriseMessagingService,IBMWebsphereMQ).JustaddtherequiredconnectionfactoryimplementationasconnectionFactorybean.
NoteAlloftheCitrusJMSendpointcomponentswillautomaticallylookforabeannamedconnectionFactorybydefault.Youcanusetheconnection-factoryendpointattributeinordertouseanotherconnectionfactoryinstancewithdifferentbeannames.
<citrus-jms:endpointid="helloServiceQueueEndpoint"destination-name="Citrus.HelloService.Request.Queue"
CitrusReferenceGuide
230Jms
![Page 231: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/231.jpg)
connection-factory="myConnectionFacotry"/>
AsanalternativetothatyoumaywanttouseaspecialSpringjmstemplateimplementationascustombeaninyourendpoint.
<citrus-jms:endpointid="helloServiceQueueEndpoint"destination-name="Citrus.HelloService.Request.Queue"jms-template="myJmsTemplate"/>
Theendpointisnowreadytobeusedinsideatestcase.Insideatestcaseyoucansendorreceivemessagesusingthisendpoint.ThetestactionscanreferencetheJMSendpointusingitsidentifier.WhensendingamessagethemessageendpointcreatesaJMSmessageproducerandwillsimplypublishthemessagetothedefinedJMSdestination.Asthecommunicationisasynchronousbydefaultproducerdoesnotwaitforasynchronousresponse.
WhenreceivingamessageswiththisendpointtheendpointcreatesaJMSconsumerontheJMSdestination.Theendpointthenactsasamessagedrivenlistener.Thismeansthatthemessageconsumerconnectstothegivendestinationandwaitsformessagestoarrive.
NoteBesidesthedestination-nameattributeyoucanalsoprovideareferencetoadestinationimplementation.
<citrus-jms:endpointid="helloServiceQueueEndpoint"destination="helloServiceQueue"/>
<amq:queueid="helloServiceQueue"physicalName="Citrus.HelloService.Request.Queue"/>
ThedestinationattributereferencestoaJMSdestinationobjectintheSpringapplicationcontext.IntheexampleaboveweusedtheActiveMQqueuedestinationcomponent.ThedestinationreferencecanalsorefertoaJNDIlookupforinstance.
JMSsynchronousendpoints
WhenusingsynchronousmessageendpointsCitruswillmanageareplydestinationforreceivingasynchronousresponsemessageonthereplydestination.Thefollowingfigureillustratesthatwenowhavetwodestinationsinourcommunicationscenario.
CitrusReferenceGuide
231Jms
![Page 232: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/232.jpg)
Thesynchronousmessageendpointcomponentissimilartotheasynchronousbrotherthatwehavediscussedbefore.Theonlydifferenceisthattheendpointwillautomaticallymanageareplydestinationbehindthescenes.BydefaultCitrususestemporaryreplydestinationsthatgetautomaticallydeletedafterthecommunicationhandshakeisdone.AgainweneedtouseaJMSconnectionfactoryintheSpringXMLconfigurationasthecomponentneedtoconnecttoaJMSmessagebroker.
<citrus-jms:sync-endpointid="helloServiceSyncEndpoint"destination-name="Citrus.HelloService.InOut.Queue"timeout="10000"/>
Thesynchronouscomponentdefinesatargetdestinationwhichagainiseitheraqueueortopicdestination.Ifnothingelseisdefinedtheendpointwillcreatetemporaryreplydestinationsonitsown.Whentheendpointhassentamessageitwaitssynchronouslyfortheresponsemessagetoarriveonthereplydestination.Youcanreceivethisreplymessageinyourtestcasebyreferencingthissameendoointinareceivetestaction.Incasenoreplymessagearrivesintimeamessagetimeouterrorisraisedrespectively.
Seethefollowingexampletestcasewhichreferencesthesynchronousmessageendpointinitssendandreceivetestactioninordertosendoutamessageandwaitforthesynchronousresponse.
<testcasename="synchronousMessagingTest"><actions><sendendpoint="helloServiceSyncEndpoint"><message><data>[...]</data></message></send>
<receiveendpoint="helloServiceSyncEndpoint"><message><data>[...]</data></message>
CitrusReferenceGuide
232Jms
![Page 233: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/233.jpg)
</receive></actions></testcase>
Weinitiatedthesynchronouscommunicationbysendingamessageonthesynchronousendpoint.Thesecondstepthenreceivesthesynchronousmessageonthetemporaryreplydestinationthatwasautomaticallycreatedforus.
Ifyouratherwanttodefineastaticreplydestinationyoucandoso,too.Thestaticreplydestinationisnotdeletedaftercommunicationhandshake.Youmayneedtoworkwithmessageselectorstheninordertopicktherightresponsemessagethatbelongstoaspecificcommunicationhandshake.Youcandefineastaticreplydestinationonthesynchronousendpointcomponentasfollows.
<citrus-jms:sync-endpointid="helloServiceSyncEndpoint"destination-name="Citrus.HelloService.InOut.Queue"reply-destination-name="Citrus.HelloService.Reply.Queue"timeout="10000"/>
Insteadofusingthereply-destination-namefeelfreetousethedestinationreferencewithreply-destinationattribute.AgainyoucanuseaJNDIlookupthentoreferenceadestinationobject.
ImportantBeawareofpermissionsthataremandatoryforcreatingtemporarydestinations.CitrustriestocreatetemporaryqueuesontheJMSmessagebroker.FollowingfromthattheCitrusJMSuserhastohavethepermissiontodoso.Besurethattheuserhasthesufficientrightswhenusingtemporaryreplydestinations.
Uptonowwehavesentamessageandwaitedforasynchronousresponseinthenextstep.Nowitisalsopossibletoswitchthedirectionsofsendandreceiveactions.ThenwehavethesituationwhereCitrusreceivesaJMSmessagefirstandthenCitrusisinchargeofprovidingapropersynchronousresponsemessagetotheinitialsender.
InthisscenariotheforeignmessageproducerhasstoredadynamicJMSreplyqueuedestinationtotheJMSheader.SoCitrushastosendthereplymessagetothisspecificreplydestination,whichisdynamicofcourse.Fortunatelytheheavyliftisdonewiththe
CitrusReferenceGuide
233Jms
![Page 234: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/234.jpg)
JMSmessageendpointandwedonothavetochangeanythinginourconfiguration.Againwejustdefineasynchronousmessageendpointintheapplicationcontext.
<citrus-jms:sync-endpointid="helloServiceSyncEndpoint"destination-name="Citrus.HelloService.InOut.Queue"timeout="10000"/>
Nowtheonlythingthatchangeshereisthatwefirstreceiveamessageinourtestcaseonthisendpoint.Thesecondstepisasendmessageactionthatreferencesthissameendpointandwearedone.Citrusautomaticallymanagesthereplydestinationsforus.
<testcasename="synchronousMessagingTest"><actions><receiveendpoint="helloServiceSyncEndpoint"><message><data>[...]</data></message></receive>
<sendendpoint="helloServiceSyncEndpoint"><message><data>[...]</data></message></send></actions></testcase>
JMStopics
UptonowwehaveusedJMSqueuedestinationsonourendpoints.CitrusisalsoabletoconnecttoJMStopicdestinations.IncontrarytoJMSqueueswhichrepresentsthepoint-to-pointcommunicationJMStopicsusepublish-subscribemechanisminordertospreadmessagesoverJMS.AJMStopicproducerpublishesmessagestothetopic,whilethetopicacceptsmultiplemessagesubscriptionsanddeliversthemessagetoallsubscribers.
TheCitrusJMSendpointsoffertheattribute'pub-sub-domain'.OncethisattributeissettotrueCitruswilluseJMStopicsinsteadofqueuedestinations.Seethefollowingexamplewherethepublish-subscribeattributeissettotrueinJMSmessageendpoint
CitrusReferenceGuide
234Jms
![Page 235: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/235.jpg)
components.
<citrus-jms:endpointid="helloServiceQueueEndpoint"destination="helloServiceQueue"pub-sub-domain="true"/>
WhenusingJMStopicsyouwillbeabletosubscribeseveraltestactionstothetopicdestinationandreceiveamessagemultipletimesasallsubscriberswillreceivethemessage.
ImportantItisveryimportanttokeepinmindthatCitrusdoesnotdealwithdurablesubscribers.Thismeansthatmessagesthatweresentinadvancetothemessagesubscriptionarenotdeliveredtothemessageendpoint.SoracingconditionsmaycauseproblemswhenusingJMStopicendpointsinCitrus.BesuretoletCitrussubscribetothetopicbeforemessagesaresenttoit.Otherwiseyoumayloosesomemessagesthatweresentinadvancetothesubscription.
JMSmessageheaders
TheJMSspecificationdefinesasetofspecialmessageheaderentriesthatcangointoyourJMSmessage.TheseJMSheadersarestoreddifferentlyinaJMSmessageheaderthanothercustomheaderentriesdo.Thereforethesespecialheadervaluesshouldbesetinaspecialsyntaxthatwediscussinthenextparagraphs.
<header><elementname="citrus_jms_correlationId"value="$correlationId"/><elementname="citrus_jms_messageId"value="$messageId"/><elementname="citrus_jms_redelivered"value="$redelivered"/><elementname="citrus_jms_timestamp"value="$timestamp"/></header>
AsyouseeallJMSspecificmessageheadersusethecitrusjmsprefix.ThisprefixcomesfromSpringIntegrationmessageheadermappersthattakecareofsettingthoseheadersintheJMSmessageheaderproperly.
TypingofmessageheaderentriesmayalsobeofinterestinordertomeettheJMSstandardsoftypedmessageheaders.ForinstancethefollowingmessageheaderisoftypedoubleandisthereforetransferredviaJMSasadoublevalue.
<header><elementname="amount"value="19.75"type="double"/></header>
CitrusReferenceGuide
235Jms
![Page 236: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/236.jpg)
SOAPoverJMS
WhensendingSOAPmessagesyouhavetodealwithproperenvelope,bodyandheaderconstruction.InCitrusyoucanaddaspecialmessageconverterthatperformstheheavyliftforyou.JustaddthemessageconvertertotheJMSendpointasshowninthenextprogramlisting:
<citrus-jms:endpointid="helloServiceSoapJmsEndpoint"destination-name="Citrus.HelloService.Request.Queue"message-converter="soapJmsMessageConverter"/>
<beanid="soapJmsMessageConverter"class="com.consol.citrus.jms.message.SoapJmsMessageConverter"
WiththismessageconverteryoucanskiptheSOAPenvelopecompletelyinyourtestcase.Youjustdealwiththemessagebodypayloadandtheheaderentries.Therestisdonebythemessageconverter.SoyougetproperSOAPmessagesontheproducerandconsumerside.
CitrusReferenceGuide
236Jms
![Page 237: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/237.jpg)
HTTPRESTsupportRESTAPIshavegainedmoreandmoresignificanceregardingclient-serverinterfaces.TheRESTclientisnothingbutaHTTPclientsendingHTTPrequestsusuallyinJSONdataformattoaHTTPserver.AsHTTPisasynchronousprotocolbynaturetheclientreceivestheserverresponsesynchronously.CitrusisabletoconnectwithHTTPservicesandtestRESTAPIsonbothclientandserversidewithapowerfulJSONmessagedatasupport.InthenextsectionsyouwilllearnhowtoinvokeHTTPservicesasaclientandhowtohandleRESTHTTPrequestsinatestcase.WedealwithsettingupaHTTPserverinordertoacceptclientrequestsandprovideproperHTTPresponseswithGET,PUT,DELETEorPOSTrequestmethod.
NoteThehttpcomponentsinCitrusarekeptinaseparateMavenmodule.SoyoushouldaddthemoduleasMavendependencytoyourprojectaccordingly.
<dependency><groupId>com.consol.citrus</groupId><artifactId>citrus-http</artifactId><version>2.7.1</version></dependency>
AsCitrusprovidesacustomizedHTTPconfigurationschemafortheSpringapplicationcontextconfigurationfileswehavetoaddnametothetoplevelbeanselement.Simplyincludethehttp-confignamespaceintheconfigurationXMLfilesasfollows.
<beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:citrus="http://www.citrusframework.org/schema/config"xmlns:citrus-http="http://www.citrusframework.org/schema/http/config"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.citrusframework.org/schema/confighttp://www.citrusframework.org/schema/config/citrus-config.xsdhttp://www.citrusframework.org/schema/http/confighttp://www.citrusframework.org/schema/http/config/citrus-http-config.xsd">
[...]
</beans>
CitrusReferenceGuide
237Http
![Page 238: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/238.jpg)
NowwearereadytousethecustomizedCitrusHTTPconfigurationelementswiththecitrus-httpnamespaceprefix.
HTTPRESTclient
OntheclientsidewehaveasimpleHTTPmessageclientcomponentconnectingtotheserver.Therequest-urlattributedefinestheHTTPserverendpointURLtoconnectto.Asusualyoucanreferencethisclientinyourtestcaseinordertosendandreceivemessages.Citrusasclientwaitsfortheresponsemessagefromserver.Afterthattheresponsemessagegoesthroughthevalidationprocessasusual.LetusseehowaCitrusHTTPclientcomponentlookslike:
<citrus-http:clientid="helloHttpClient"request-url="http://localhost:8080/hello"request-method="GET"content-type="application/xml"timeout="60000"/>
Therequest-methoddefinestheHTTPmethodtouse.Inadditiontothatwecanspecifythecontent-typeoftherequestweareabouttosend.TheclientbuildstheHTTPrequestandsendsittotheHTTPserver.WhiletheclientiswaitingforthesynchronousHTTPresponsetoarriveweareabletopollseveraltimesfortheresponsemessageinourtestcase.Asusualaoucanusethesameclientendpointinyourtestcasetosendandreceivemessagessynchronously.Incasethereplymessagecomesintoolateaccordingtothetimeoutsettingsarespectivetimeouterrorisraised.
HttpdefinesseveralrequestmethodsthataclientcanusetoaccessHttpserverresources.IntheexampleclientaboveweareusingGETasdefaultrequestmethod.OfcourseyoucanoverwritethissettinginatestcaseactionbysettingtheHTTPrequestmethodinsidethesendingtestaction.TheHttpclientcomponentcanbeusedasnormalendpointinasendingtestaction.Usesomethinglikethisinyourtest:
XMLDSL
<sendendpoint="helloHttpClient"><message><payload><TestMessage><Text>HelloHttpServer</Text></TestMessage></payload></message>
CitrusReferenceGuide
238Http
![Page 239: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/239.jpg)
<header><elementname="citrus_http_method"value="POST"/></header></send>
TipCitrususestheSpringRESTtemplatemechanismforsendingoutHTTPrequests.ThismeansyouhavegreatcustomizingopportunitieswithaspecialRESTtemplateconfiguration.YoucanthinkofbasicHTTPauthentication,readtimeoutsandspecialmessagefactoryimplementations.JustusethecustomRESTtemplateattributeinclientconfigurationlikethis:
<citrus-http:clientid="helloHttpClient"request-url="http://localhost:8080/hello"request-method="GET"content-type="text/plain"rest-template="customizedRestTemplate"/>
<!--Customizedresttemplate--><beanname="customizedRestTemplate"class="org.springframework.web.client.RestTemplate"><propertyname="messageConverters"><util:listid="converter"><beanclass="org.springframework.http.converter.StringHttpMessageConverter"><propertyname="supportedMediaTypes"><util:listid="types"><value>text/plain</value></util:list></property></bean></util:list></property><propertyname="errorHandler"><!--Customerrorhandler--></property><propertyname="requestFactory"><beanclass="org.springframework.http.client.HttpComponentsClientHttpRequestFactory"><propertyname="readTimeout"value="9000"/></bean></property></bean>
UptonowwehaveusedanormalsendtestactiontosendHttprequestsasaclient.ThisiscompletelyvalidstrategyastheCitrusHttpclientisanormalendpoint.ButwemightwanttosetsomemoreHttpRESTspecificpropertiesandsettings.InordertosimplifytheHttpusageinatestcasewecanuseaspecialtestactionimplementation.TheCitrusHttpspecificactionsarelocatedinaseparateXMLnamespace.SowenneedtoaddthisnamespacetoourtestcaseXMLfirst.
CitrusReferenceGuide
239Http
![Page 240: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/240.jpg)
<beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:http="http://www.citrusframework.org/schema/http/testcase"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.citrusframework.org/schema/http/testcasehttp://www.citrusframework.org/schema/http/testcase/citrus-http-testcase.xsd">
[...]
</beans>
ThetestcaseisnowreadytousethespecificHttptestactionsbyusingtheprefixhttp:.
XMLDSL
<http:send-requestclient="httpClient"><http:POSTpath="/customer"><http:headerscontent-type="application/xml"accept="application/xml,*/*"><http:headername="X-CustomHeaderId"value="$custom_header_id"/></http:headers><http:body><http:data><![CDATA[<customer><id>citrus:randomNumber()</id><name>testuser</name></customer>]]></http:data></http:body></http:POST></http:send-request>
TheactionaboveusesseveralHttpspecificsettingssuchastherequestmethodPOSTaswellasthecontent-typeandacceptheaders.AsusualthesendactionneedsatargetHttpclientendpointcomponent.Wecanspecifyarequestpathattributethataddedasrelativepathtothebaseuriusedontheclient.
WhenusingaGETrequestwecanspecifysomerequesturiparameters.
XMLDSL
<http:send-requestclient="httpClient"><http:GETpath="/customer/$custom_header_id"><http:paramscontent-type="application/xml"accept="application/xml,*/*">
CitrusReferenceGuide
240Http
![Page 241: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/241.jpg)
<http:paramname="type"value="active"/></http:params></http:GET></http:send-request>
ThesendactionaboveusesaGETrequestontheendpointurihttp://localhost:8080/customer/1234?type=active.
OfcoursewhensendingHttpclientrequestswearealsointerestedinreceivingHttpresponsemessages.WewanttovalidatethesuccessresponsewithHttpstatuscode.
XMLDSL
<http:receive-responseclient="httpClient"><http:headersstatus="200"reason-phrase="OK"version="HTTP/1.1"><http:headername="X-CustomHeaderId"value="$custom_header_id"/></http:headers><http:body><http:data><![CDATA[<customerResponse><success>true</success></customerResponse>]]></http:data></http:body></http:receive-response>
Thereceive-responsetestactionalsousesaclientcomponent.Wecanexpectresponsestatuscodeinformationsuchasstatusandreason-phrase.OfcourseCitruswillraiseavalidationexceptionincaseHttpstatuscodesmismatch.
UptonowwehaveusedXMLDSLtestcases.TheJavaDSLinCitrusalsoworkswithspecificHttptestactions.Seefollowingexampleandfindouthowthisworks:
XMLDSL
@CitrusTestpublicvoidhttpActionTest()http().client("httpClient").send().post("/customer").payload("<customer>"+"<id>citrus:randomNumber()</id>"+"<name>testuser</name>"+"</customer>").header("X-CustomHeaderId","$custom_header_id")
CitrusReferenceGuide
241Http
![Page 242: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/242.jpg)
.contentType("text/xml").accept("text/xml,*/*");
http().client("httpClient").receive().response(HttpStatus.OK).payload("<customerResponse>"+"<success>true</success>"+"</customerResponse>").header("X-CustomHeaderId","$custom_header_id").version("HTTP/1.1");
Thereisonemoresettingontheclienttobeawareof.BydefaulttheclientcomponentwilladdtheAccepthttpheaderandsetitsvaluetoalistofallsupportedencodingsonthehostoperatingsystem.Asthislistcangetverylongyoumaywanttonotsetthisdefaultacceptheader.ThesettingisdoneintheSpringRestTemplate:
<beanname="customizedRestTemplate"class="org.springframework.web.client.RestTemplate"><propertyname="messageConverters"><util:listid="converter"><beanclass="org.springframework.http.converter.StringHttpMessageConverter"><propertyname="writeAcceptCharset"value="false"/></bean></util:list></property></bean>
YouwouldhaveaddthiscustomRestTemplateconfigurationandsetittotheclientcomponentwithrest-templateproperty.ButfortunatelytheCitrusclientcomponentprovidesaseparatesettingdefault-accept-headerwhichisaBooleansetting.Bydefaultitissettotruesothedefaultacceptheaderisautomaticallyaddedtoallrequests.Ifyousetthisflagtofalsetheheaderisnotset:
<citrus-http:clientid="helloHttpClient"request-url="http://localhost:8080/hello"request-method="GET"content-type="text/plain"default-accept-header="false"/>
OfcourseyoucansettheAcceptheaderoneachsendoperationinordertotelltheserverwhatkindofcontenttypesaresupportedinresponsemessages.
CitrusReferenceGuide
242Http
![Page 243: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/243.jpg)
NowwecansendandreceivemessagesasHttpclientwithspecifictestactions.NowletsmoveontotheHttpserver.
HTTPclientinterceptors
Theclientcomponentisabletoaddcustominterceptorsthatparticipateintherequest/responseprocessing.Theinterceptorsneedtoimplementthecommoninterfaceorg.springframework.http.client.ClientHttpRequestInterceptor.
<citrus-http:clientid="helloHttpClient"request-url="http://localhost:8080/hello"request-method="GET"interceptors="clientInterceptors"/>
<util:listid="clientInterceptors"><beanclass="com.consol.citrus.http.interceptor.LoggingClientInterceptor"/></util:list>
ThesampleaboveaddstheCitrusloggingclientinterceptorthatlogsrequestsandresponsesexchangedwiththatclientcomponent.Youcanaddcustominterceptorimplementationshereinordertoparticipateintherequest/responsemessageprocessing.
HTTPRESTserver
TheHTTPclientwasquiteeasyandstraightforward.ReceivingHTTPmessagesisalittlebitmorecomplicatedbecauseCitrushastoprovideserverfunctionalitylisteningonalocalportforclientconnections.ThereforeCitrusoffersanembeddedHTTPserverwhichiscapableofhandlingincomingHTTPrequests.OnceaclientconnectionisacceptedtheHTTPservermustalsoprovideaproperHTTPresponsetotheclient.InthenextfewlinesyouwillseehowtosimulateserversideHTTPRESTservicewithCitrus.
<citrus-http:serverid="helloHttpServer"port="8080"auto-start="true"resource-base="src/it/resources"/>
CitrususesanembeddedJettyserverthatwillautomaticallystartwhentheSpringapplicationcontextisloaded(auto-start="true").Thebasicconnectorislisteningonport8080forrequests.Testcasescaninteractwiththisserverinstanceviamessage
CitrusReferenceGuide
243Http
![Page 244: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/244.jpg)
channelsbydefault.Theserverprovidesaninboundchannelthatholdsincomingrequestmessages.Thetestcasecanreceivethoserequestsfromthechannelwithanormalreceivetestaction.InasecondstepthetestcasecanprovideasynchronousresponsemessageasreplywhichwillbeautomaticallysentbacktotheHTTPclientasresponse.
Thefigureaboveshowsthebasicsetupwithinboundchannelandreplychannel.Youasatestershouldnotworryaboutthistomuch.Bydefaultyouasatesterjustusetheserverassynchronousendpointinyourtestcase.Thismeansthatyousimplyreceiveamessagefromtheserverandsendaresponseback.
<testcasename="httpServerTest"><actions><receiveendpoint="helloHttpServer"><message><data>[...]</data></message></receive>
<sendendpoint="helloHttpServer"><message><data>[...]</data></message></send></actions></testcase>
Asyoucanseewereferencetheserveridinbothreceiveandsendactions.TheCitrusserverinstancewillautomaticallysendtheresponsebacktothecallingHTTPclient.Inmostcasesthisisexactlywhatwewanttodo-sendbackaresponsemessagethatisspecifiedinsidethetest.TheHTTPservercomponentbydefaultusesachannelendpointadapterinordertoforwardallincomingrequeststoaninmemorymessagechannel.Thisisdonecompletelybehindthescenes.TheHttpservercomponentprovidessomemorecustomizationpossibilitieswhenitcomestoendpointadapter
CitrusReferenceGuide
244Http
![Page 245: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/245.jpg)
implementations.Thistopicisdiscussedinaseparatesectionendpoint-adapter.Uptonowwekeepitsimplebysynchronouslyreceivingandsendingmessagesinthetestcase.
TipThedefaultchannelendpointadapterautomaticallycreatesaninboundmessagechannelwhereincomingmessagesarestoredtointernally.Soifyouneedtocleanupaserverthathasalreadystoredsomeincomingmessagesyoucandothiseasilybypurgingtheinternalmessagechannel.ThemessagechannelfollowsanamingconventionserverName.inboundwhereserverNameistheSpringbeannameoftheCitrusserverendpointcomponent.Ifyoupurgethisinternalchannelinabeforetestnatureyouaresurethatobsoletemessagesonaserverinstancegetpurgedbeforeeachtestisexecuted.
Soletsgetbacktoourmissionofprovidingresponsemessagesasservertoconnectedclients.AsyoumightknowHttpRESTworkswithsomecharacteristicpropertieswhenitcomestosendandreceivemessages.ForinstanceaclientcansenddifferentrequestmethodsGET,POST,PUT,DELETE,HEADandsoon.TheCitrusservermayverifythismethodwhenreceivingclientrequests.ThereforewehaveintroducedspecialHttptestactionsforservercommunication.Havealookatasimpleexample:
<http:receive-requestserver="helloHttpServer"><http:POSTpath="/test"><http:headerscontent-type="application/xml"accept="application/xml,*/*"><http:headername="X-CustomHeaderId"value="$custom_header_id"/><http:headername="Authorization"value="Basicc29tZVVzZXJuYW1lOnNvbWVQYXNzd29yZA=="/></http:headers><http:body><http:data><![CDATA[<testRequestMessage><text>HelloHttpServer</text></testRequestMessage>]]></http:data></http:body></http:POST><http:extract><http:headername="X-MessageId"variable="message_id"/></http:extract></http:receive-request>
<http:send-responseserver="helloHttpServer"><http:headersstatus="200"reason-phrase="OK"version="HTTP/1.1"><http:headername="X-MessageId"value="$message_id"/><http:headername="X-CustomHeaderId"value="$custom_header_id"/><http:headername="Content-Type"value="application/xml"/>
CitrusReferenceGuide
245Http
![Page 246: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/246.jpg)
</http:headers><http:body><http:data><![CDATA[<testResponseMessage><text>HelloCitrus</text></testResponseMessage>]]></http:data></http:body></http:send-response>
WereceiveaclientrequestandvalidatethattherequestmethodisPOSTonrequestpath/test.Nowwecanvalidatespecialmessageheaderssuchascontent-type.Inadditiontothatwecancheckcustomheadersandbasicauthorizationheaders.Asusualtheoptionalmessagebodyiscomparedtoanexpectedmessagetemplate.ThecustomX-MessageIdheaderissavedtoatestvariablemessage_idforlaterusageintheresponse.
TheresponsemessagedefinesHttptypicalentitiessuchasstatusandreason-phrase.Herethetestercansimulate404NOT_FOUNDerrorsorsimilarotherstatuscodesthatgetsendbacktotheclient.InourexampleeverythingisOKandwesendbackaresponsebodyandsomecustomheaderentries.
ThatisbasicallyhowCitrussimulatesHttpserveroperations.Wereceivetheclientrequestandvalidatetherequestproperties.ThenwesendbackaresponsewithaHttpstatuscode.
AsusualalltheseHttpspecificactionsarealsoavailableinJavaDSL.
@CitrusTestpublicvoidhttpServerActionTest()http().server("helloHttpServer").receive().post("/test").payload("<testRequestMessage>"+"<text<HelloHttpServer</text>"+"</testRequestMessage>").contentType("application/xml").accept("application/xml,*/*").header("X-CustomHeaderId","$custom_header_id").header("Authorization","Basicc29tZVVzZXJuYW1lOnNvbWVQYXNzd29yZA==").extractFromHeader("X-MessageId","message_id");
http().server("helloHttpServer")
CitrusReferenceGuide
246Http
![Page 247: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/247.jpg)
.send().response(HttpStatus.OK).payload("<testResponseMessage>"+"<text<HelloCitrus</text>"+"</testResponseMessage>").version("HTTP/1.1").contentType("application/xml").header("X-CustomHeaderId","$custom_header_id").header("X-MessageId","$message_id");
ThisistheexactsameexampleinJavaDSL.Weselectserveractionsfirstandreceiveclientrequests.ThenwesendbackaresponsewithaHttpStatus.OKstatus.ThiscompletestheserveractionsonHttpmessagetransport.NowwecontinuewithsomemoreHttpspecificsettingsandfeatures.
HTTPheaders
WhendealingwithHTTPrequest/responsecommunicationwealwaysdealwithHTTPspecificheaders.TheHTTPprotocoldefinesagroupofheaderattributesthatbothclientandserverneedtobeabletohandle.YoucansetandvalidatetheseHTTPheadersinCitrusquiteeasy.LetushavealookataclientoperationinCitruswheresomeHTTPheadersareexplicitlysetbeforetherequestissentout.
<http:send-requestclient="httpClient"><http:POST><http:headers><http:headername="X-CustomHeaderId"value="$custom_header_id"/><http:headername="Content-Type"value="text/xml"/><http:headername="Accept"value="text/xml,*/*"/></http:headers><http:body><http:payload><testRequestMessage><text>HelloHttpServer</text></testRequestMessage></http:payload></http:body></http:POST></http:send-request>
Weareabletosetcustomheaders(X-CustomHeaderId)thatgodirectlyintotheHTTPheadersectionoftherequest.InadditiontothattesterscanexplicitlysetHTTPreservedheaderssuchasContent-Type.Fortunatelyyoudonothavetosetallheadersonyour
CitrusReferenceGuide
247Http
![Page 248: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/248.jpg)
own.CitruswillautomaticallysettherequiredHTTPheadersfortherequest.SowehavethefollowingHTTPrequestwhichissenttotheserver:
POST/testHTTP/1.1Accept:text/xml,*/*Content-Type:text/xmlX-CustomHeaderId:123456789Accept-Charset:macromanUser-Agent:JakartaCommons-HttpClient/3.1Host:localhost:8091Content-Length:175<testRequestMessage><text>HelloHttpServer</text></testRequestMessage>
OnserversidetestersareinterestedinvalidatingtheHTTPheaders.WithinCitrusreceiveactionyousimplydefinetheexpectedheaderentries.TheHTTPspecificheadersareautomaticallyavailableforvalidationasyoucanseeinthisexample:
<http:receive-requestserver="httpServer"><http:POST><http:headers><http:headername="X-CustomHeaderId"value="$custom_header_id"/><http:headername="Content-Type"value="text/xml"/><http:headername="Accept"value="text/xml,*/*"/></http:headers><http:body><http:payload><testRequestMessage><text>HelloHttpServer</text></testRequestMessage></http:payload></http:body></http:POST></http:receive-request>
ThetestchecksoncustomheadersandHTTPspecificheaderstomeettheexpectedvalues.
NowthatwehaveacceptedtheclientrequestandvalidatedthecontentsweareabletosendbackaproperHTTPresponsemessage.SamethingherewithHTTPspecificheaders.TheHTTPprotocoldefinesseveralheadersmarkingthesuccessorfailureoftheserveroperation.InthetestcaseyoucansetthoseheadersfortheresponsemessagewithconventionalCitrusheadernames.Seethefollowingexampletofindouthowthatworksforyou.
CitrusReferenceGuide
248Http
![Page 249: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/249.jpg)
<http:send-responseserver="httpServer"><http:headersstatus="200"reason-phrase="OK"><http:headername="X-CustomHeaderId"value="$custom_header_id"/><http:headername="Content-Type"value="text/xml"/></http:headers><http:body><http:payload><testResponseMessage><text>HelloCitrusClient</text></testResponseMessage></http:payload></http:body></http:send-response>
Oncemorewesetthecustomheaderentry(X-CustomHeaderId)andaHTTPreservedheader(Content-Type)fortheresponsemessage.OntopofthisweareabletosettheresponsestatusfortheHTTPresponse.Weusethereservedheadernamesstatusinordertomarkthesuccessoftheserveroperation.WiththismechanismwecaneasilysimulatedifferentserverbehavioursuchasHTTPerrorresponsecodes(e.g.404-Notfound,500-Internalerror).Letushaveacloserlookatthegeneratedresponsemessage:
HTTP/1.1200OKContent-Type:text/xml;charset=UTF-8Accept-Charset:macromanContent-Length:205Server:Jetty(7.0.0.pre5)<testResponseMessage><text>HelloCitrusClient</text></testResponseMessage>
TipYoudonothavetosetthereasonphraseallthetime.ItissufficienttoonlysettheHTTPstatuscode.CitruswillautomaticallyaddtheproperreasonphraseforwellknownHTTPstatuscodes.
TheonlythingthatismissingrightnowisthevalidationofHTTPstatuscodeswhenreceivingtheserverresponseinaCitrustestcase.ItisveryeasyasyoucanusetheCitrusreservedheadernamesforvalidation,too.
<http:receive-responseclient="httpClient"><http:headersstatus="200"reason-phrase="OK"version="HTTP/1.1"><http:headername="X-CustomHeaderId"value="$custom_header_id"/></http:headers><http:body>
CitrusReferenceGuide
249Http
![Page 250: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/250.jpg)
<http:payload><testResponseMessage><text>HelloTestFramework</text></testResponseMessage></http:payload></http:body></http:receive-response>
UptonowwehaveusedsomeofthebasicCitrusreservedHTTPheadernames(status,version,reason-phrase).InHTTPRESTfulservicessomeotherheadernamesareessentialforvalidation.Thesearerequestattributeslikequeryparameters,contextpathandrequestURI.TheCitrusserversideRESTmessagecontrollerwillautomaticallyaddallthisinformationtothemessageheaderforyou.Soallyouneedtodoisvalidatetheheaderentriesinyourtest.
ThenextexamplereceivesaHTTPGETmethodrequestonserverside.HeretheGETrequestdoesnothaveanymessagepayload,sothevalidationjustworksontheinformationgiveninthemessageheader.Weassumetheclienttocallhttp://localhost:8080/app/users?id=123456789.Asatesterweneedtovalidatetherequestmethod,requestURI,contextpathandthequeryparameters.
<http:receive-requestserver="httpServer"><http:GETpath="/app/users"context-path="/app"><http:params><http:paramname="id"value="123456789"/></http:params><http:headers><http:headername="Host"value="localhost:8080"/><http:headername="Content-Type"value="text/html"/><http:headername="Accept"value="text/xml,*/*"/></http:headers><http:body><http:data></http:data></http:body></http:GET></http:receive-request>
TipBeawareoftheslightdifferencesinrequestURIandcontextpath.Thecontextpathgivesyouthewebapplicationcontextpathwithintheservletcontainerforyourwebapplication.TherequestURIalwaysgivesyouthecompletepaththatwascalledforthisrequest.
CitrusReferenceGuide
250Http
![Page 251: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/251.jpg)
AsyoucanseeweareabletovalidateallpartsoftheinitialrequestendpointURItheclientwascalling.ThiscompletestheHTTPheaderprocessingwithinCitrus.OnbothclientandserversideCitrusisabletosetandvalidateHTTPspecificheaderentrieswhichisessentialforsimulatingHTTPcommunication.
HTTPserverinterceptors
Theservercomponentisabletoaddcustominterceptorsthatparticipateintherequest/responseprocessing.Theinterceptorsneedtoimplementthecommoninterfaceorg.springframework.web.servlet.HandlerInterceptor.
<citrus-http:serverid="httpServer"port="8080"auto-start="true"interceptors="serverInterceptors"/>
<util:listid="serverInterceptors"><beanclass="com.consol.citrus.http.interceptor.LoggingHandlerInterceptor"/></util:list>
ThesampleaboveaddstheCitruslogginghandlerinterceptorthatlogsrequestsandresponsesexchangedwiththatservercomponent.Youcanaddcustominterceptorimplementationshereinordertoparticipateintherequest/responsemessageprocessing.
HTTPformurlencodeddata
HTMLformdatacanbesenttotheserverusingdifferentmethodsandcontenttypes.OneofthemisaPOSTmethodwithx-www-form-urlencodedbodycontent.Theformdataelementsaresenttotheserverusingkey-valuepairsPOSTdatawheretheformcontrolnameisthekeyandthecontroldataistheurlencodedvalue.
Formurlencodedformdatacontentcouldlooklikethis:
password=s%21cr%21t&username=foo
Ayoucanseetheformdataisautomaticallyencoded.Intheexampleabovewetransmittwoformcontrolspasswordandusernamewithrespectivevaluess$cr$tandfoo.IncasewewouldvalidatethisformdatainCitrusweareabletodothiswithplaintextmessagevalidation.
CitrusReferenceGuide
251Http
![Page 252: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/252.jpg)
<receiveendpoint="httpServer"><messagetype="plaintext"><data><![CDATA[password=s%21cr%21t&username=$username]]></data></message><header><elementname="citrus_http_method"value="POST"/><elementname="citrus_http_request_uri"value="/form-test"/><elementname="Content-Type"value="application/x-www-form-urlencoded"/></header></receive>
Obviouslyvalidatingthesekey-valuepaircharactersequencescanbehardespeciallywhenhavingHTMLformswithlotsofformcontrols.ThisiswhyCitrusprovidesaspecialmessagevalidatorforx-www-form-urlencodedcontents.Firstofallwehavetoaddcitrus-httpmoduleasdependencytoourprojectifnotdonesoyet.AfterthatwecanaddthevalidatorimplementationtothelistofmessagevalidatorsusedinCitrus.
<citrus:message-validators><citrus:validatorclass="com.consol.citrus.http.validation.FormUrlEncodedMessageValidator"/></citrus:message-validators>
Nowweareabletoreceivetheurlencodedformdatamessageinatest.
<receiveendpoint="httpServer"><messagetype="x-www-form-urlencoded"><payload><form-dataxmlns="http://www.citrusframework.org/schema/http/message"><content-type>application/x-www-form-urlencoded</content-type><action>/form-test</action><controls><controlname="password"><value>$password</value></control><controlname="username"><value>$username</value></control></controls></form-data></payload></message><header><elementname="citrus_http_method"value="POST"/>
CitrusReferenceGuide
252Http
![Page 253: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/253.jpg)
<elementname="citrus_http_request_uri"value="/form-test"/><elementname="Content-Type"value="application/x-www-form-urlencoded"/></header></receive>
Weuseaspecialmessagetypex-www-form-urlencodedsothenewmessagevalidatorwilltakeaction.TheformurlencodedmessagevalidatorisabletohandleaspecialXMLrepresentationoftheformdata.ThisenablestheverypowerfulXMLmessagevalidationcapabilitiesofCitrussuchasignoringelementsandusageoftestvariablesinline.
Eachformcontrolistranslatedtoacontrolelementwithrespectivenameandvalueproperties.Theformdataisvalidatedinamorecomfortablewayastheplaintextmessagevalidatorwouldbeabletooffer.
HTTPerrorhandling
SofarwehavereceivedresponsemessageswithHTTPstatuscode200OK.Howtodealwithservererrorslike404NotFoundor500Internalservererror?ThedefaultHTTPmessageclienterrorstrategyistopropagateservererrorresponsemessagestothereceiveactionforvalidation.WesimplycheckonHTTPstatuscodeandstatustextforerrorvalidation.
<http:send-requestclient="httpClient"><http:body><http:payload><testRequestMessage><text>HelloHttpServer</text></testRequestMessage></http:payload></http:body></http:send-request>
<http:receive-requestclient="httpClient"><http:body><http:data><![CDATA[]]></http:data></http:body><http:headersstatus="403"reason-phrase="FORBIDDEN"/></http:receive>
Themessagedatacanbeemptydependingontheserverlogicfortheseerrorsituations.Ifwereceiveadditionalerrorinformationasmessagepayloadjustaddvalidationassertionsasusual.
CitrusReferenceGuide
253Http
![Page 254: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/254.jpg)
InsteadofreceivingsuchemptymessageswithchecksonHTTPstatusheaderinformationwecanchangetheerrorstrategyinthemessagesendercomponentinordertoautomaticallyraiseexceptionsonresponsemessagesotherthan200OK.ThereforewegobacktotheHTTPmessagesenderconfigurationforchangingtheerrorstrategy.
<citrus-http:clientid="httpClient"request-url="http://localhost:8080/test"error-strategy="throwsException"/>
Nowweexpectanexceptiontobethrownbecauseoftheerrorresponse.Followingfromthatwehavetochangeourtestcase.InsteadofreceivingtheerrormessagewithreceiveactionweasserttheclientexceptionandcheckontheHTTPstatuscodeandstatustext.
<assertexception="org.springframework.web.client.HttpClientErrorException"message="403Forbidden"><when><http:send-requestclient="httpClient"><http:body><http:payload><testRequestMessage><text>HelloHttpServer</text></testRequestMessage></http:payload></http:body></http:send-request></when></assert>
BothwaysofhandlingHTTPerrormessagesonclientsidearevalidforexpectingtheservertoraiseHTTPerrorcodes.Choosethepreferredwayaccordingtoyourtestprojectrequirements.
HTTPclientbasicauthentication
Asclientyoumayhavetousebasicauthenticationinordertoaccessaresourceontheserver.Inmostcasesthiswillbeusername/passwordauthenticationwherethecredentialsaretransmittedintherequestheadersectionasbase64encoding.
TheeasiestapproachtosettheAuthorizationheaderforabasicauthenticationHTTPrequestwouldbetosetitonyourowninthesendactiondefinition.Ofcourseyouhavetousethecorrectbasicauthenticationheadersyntaxwithbase64encodingforthe
CitrusReferenceGuide
254Http
![Page 255: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/255.jpg)
username:passwordphrase.Seethissimpleexample.
<http:headers><http:headername="Authorization"value="Basicc29tZVVzZXJuYW1lOnNvbWVQYXNzd29yZA=="/></http:headers>
CitruswilladdthisheadertotheHTTPrequestsandtheserverwillreadtheAuthorizationusernameandpassword.Formoreconvenientbase64encodingyoucanalsouseaCitrusfunction,seefunctions-encode-base64
NowthereisamorecomfortablewaytosetthebasicauthenticationheaderinalltheCitrusrequests.AsCitrususesSpring'sRESTsupportwiththeRestTemplateandClientHttpRequestFactorythebasicauthenticationisalreadycoveredthereinamoregenericway.YousimplyhavetoconfigurethebasicauthenticationcredentialsontheRestTemplate'sClientHttpRequestFactory.Justseethefollowingexampleandlearnhowtodothat.
<citrus-http:clientid="httpClient"request-method="POST"request-url="http://localhost:8080/test"request-factory="basicAuthFactory"/>
<beanid="basicAuthFactory"class="com.consol.citrus.http.client.BasicAuthClientHttpRequestFactory"><propertyname="authScope"><beanclass="org.apache.http.auth.AuthScope"><constructor-argvalue="localhost"/><constructor-argvalue="8072"/><constructor-argvalue=""/><constructor-argvalue="basic"/></bean></property><propertyname="credentials"><beanclass="org.apache.http.auth.UsernamePasswordCredentials"><constructor-argvalue="someUsername"/><constructor-argvalue="somePassword"/></bean></property></bean>
Theadvantagesofthismethodisobvious.Nowallsendingtestactionsthatreferencetheclientcomponentwillautomaticallyaddthebasicauthenticationheader.
CitrusReferenceGuide
255Http
![Page 256: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/256.jpg)
ImportantSinceCitrushasupgradedtoSpring3.1.xtheJakartacommonsHTTPclientisdeprecatedwithCitrusversion1.2.TheformerlyusedUserCredentialsClientHttpRequestFactoryisthereforealsodeprecatedandwillnotcontinuewithnextversions.PleaseupdateyourconfigurationifyouarecomingfromCitrus1.1orearlierversions.
TheaboveconfigurationresultsinHTTPclientrequestswithauthenticationheadersproperlysetforbasicauthentication.TheclientrequestfactorytakescareonaddingtheproperbasicauthenticationheadertoeachrequestthatissentwiththisCitrusmessagesender.Citrususespreemtiveauthentication.Themessagesenderonlysendsasinglerequesttotheserverwithallauthenticationinformationsetinthemessageheader.Therequestwhichdeterminestheauthenticationschemeontheserverisskipped.ThisiswhyyouhavetoaddsomeauthscopeintheclientrequestfactorysoCitruscansetupanauthenticationcachewithintheHTTPcontextinordertohavepreemtiveauthentication.
AsaresultofthebasicauthclientrequestfactorythefollowingexamplerequestthatiscreatedbytheCitrusHTTPclienthastheAuthorizationheaderset.ThisisdonenowautomaticallyforallrequestswiththisHTTPclient.
POST/testHTTP/1.1Accept:text/xml,*/*Content-Type:text/xmlAccept-Charset:iso-8859-1,us-ascii,utf-8Authorization:Basicc29tZVVzZXJuYW1lOnNvbWVQYXNzd29yZA==User-Agent:JakartaCommons-HttpClient/3.1Host:localhost:8080Content-Length:175<testRequestMessage><text>HelloHttpServer</text></testRequestMessage>
HTTPserverbasicauthentication
Citrusasaservercanalsosetbasicauthenticationsoclientsneedtoauthenticateproperlywhenaccessingserverresources.
<citrus-http:serverid="basicAuthHttpServer"port="8090"auto-start="true"resource-base="src/it/resources"security-handler="basicSecurityHandler"/>
CitrusReferenceGuide
256Http
![Page 257: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/257.jpg)
<beanid="securityHandler"class="com.consol.citrus.http.security.SecurityHandlerFactory"><propertyname="users"><list><beanclass="com.consol.citrus.http.security.User"><propertyname="name"value="citrus"/><propertyname="password"value="secret"/><propertyname="roles"value="CitrusRole"/></bean></list></property><propertyname="constraints"><map><entrykey="/foo/*"><beanclass="com.consol.citrus.http.security.BasicAuthConstraint"><constructor-argvalue="CitrusRole"/></bean></entry></map></property></bean>
Wehavesetasecurityhandlerontheserverwebcontainerwithaconstraintonallresourceswith/foo/*.Followingfromthattheserverrequiresbasicauthenticationfortheseresources.Thegrantedusersandrolesarespecifiedwithinthesecurityhandlerbeandefinition.ConnectingclientshavetosetthebasicauthHTTPheaderproperlyusingthecorrectuserandroleforaccessingtheCitrusservernow.
Youcancustomizethesecurityhandlerforyourveryspecificneeds(e.g.loadusersandroleswithJDBCfromadatabase).Justhavealookatthecodebaseandinspectthesettingsandpropertiesofferedbythesecurityhandlerinterface.
TipThismechanismisnotrestrictedtobasicauthenticationonly.Withothersettingsyoucanalsosetupdigestorform-basedauthenticationconstraintsveryeasy.
HTTPGzipcompression
Gzipisaverypopularcompressionmechanismforoptimizingthemessagetransportationforlargecontent.TheCitrushttpclientandservercomponentssupportgzipcompressionoutofthebox.Thismeansthatyouonlyneedtosetthespecificencodingheadersinyourhttprequest/responsemessage.
Accept-Encoding=gzipSettingforclientswhenrequestinggzipcompressedresponsecontent.TheHttpservermustsupportgzipcompressiontheninordertoprovidetheresponseaszippedbytestream.TheCitrushttpservercomponentautomaticallyrecognizesthisheaderinarequestandappliesgzipcompressionto
CitrusReferenceGuide
257Http
![Page 258: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/258.jpg)
theresponse.Content-Encoding=gzipWhenahttpserversendscompressedmessagecontenttotheclientthisheaderissettogzipinordertomarkthecompression.TheHttpclientmustsupportgzipcompressiontheninordertounzipthemessagecontent.TheCitrushttpclientcomponentautomaticallyrecognizesthisheaderinaresponseandappliesgzipunziplogicbeforepassingthemessagetothetestcase.
TheCitrusclientandserverautomaticallytakecareongzipcompressionwhenthoseheadersareset.Inthetestcaseyoudonotneedtoziporunzipthecontentthenasitisautomaticallydonebefore.
ThismeansthatyoucanrequestgzippedcontentfromaserverwithjustaddingthemessageheaderAccept-Encodinginyourhttprequestoperation.
<echo><message>SendHttpclientrequestforgzipcompresseddata</message></echo>
<http:send-requestclient="gzipClient"><http:POST><http:headerscontent-type="text/html"><http:headername="Accept-Encoding"value="gzip"/><http:headername="Accept"value="text/plain"/></http:headers></http:POST></http:send-request>
<echo><message>Receivetextautomaticallygzipunzipped</message></echo>
<http:receive-responseclient="gzipClient"><http:headersstatus="200"reason-phrase="OK"><http:headername="Content-Type"value="text/plain"/></http:headers><http:bodytype="plaintext"><http:data>$text</http:data></http:body></http:receive-response>
OntheserversideifwereceiveamessageandtheresponseshouldbecompressedwithGzipwejusthavetosettheContent-Encodingheaderintheresponseoperation.
<echo><message>Receivegzipcompressedasbase64encodedtext</message></echo>
CitrusReferenceGuide
258Http
![Page 259: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/259.jpg)
<http:receive-requestserver="echoHttpServer"><http:POSTpath="/echo"><http:headers><http:headername="Content-Type"value="text/html"/><http:headername="Accept-Encoding"value="gzip"/><http:headername="Accept"value="text/plain"/></http:headers></http:POST></http:receive-request>
<echo><message>SendHttpservergzipcompressedresponse</message></echo>
<http:send-responseserver="echoHttpServer"><http:headersstatus="200"reason-phrase="OK"><http:headername="Content-Encoding"value="gzip"/><http:headername="Content-Type"value="text/plain"/></http:headers><http:body><http:data>$text</http:data></http:body></http:send-response>
SotheCitrusserverwillautomaticallyaddgzipcompressiontotheresponseforus.
Ofcourseyoucanalsosendgzippedcontentasaclient.ThenyouwouldjustsettheContent-Encodingheadertogzipinyourrequest.Theclientwillautomaticallyapplycompressionforyou.
HTTPservletcontextcustomization
TheCitrusHTTPserverusesSpringapplicationcontextloadingonstartup.ForhighcustomizationsyoucanprovideacustomservletcontextfilewhichholdsallcustomconfigurationsasSpringbeansfortheserver.HereisasampleservletcontextwithsomebasicSpringMVCcomponentsandthecentralHttpMessageControllerwhichisresponsibleforhandlingincomingrequests(GET,PUT,DELETE,POST,etc.).
<beanid="citrusHandlerMapping"class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"
<beanid="citrusMethodHandlerAdapter"class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"<propertyname="messageConverters"><util:listid="converters"><beanclass="org.springframework.http.converter.StringHttpMessageConverter"><propertyname="supportedMediaTypes"><util:list>
CitrusReferenceGuide
259Http
![Page 260: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/260.jpg)
<value>text/xml</value></util:list></property></bean></util:list></property></bean>
<beanid="citrusHttpMessageController"class="com.consol.citrus.http.controller.HttpMessageController"<propertyname="endpointAdapter"><beanclass="com.consol.citrus.endpoint.adapter.EmptyResponseEndpointAdapter"/></property></bean>
ThebeansaboveareresponsibleforproperHTTPserverconfiguration.Ingeneralyoudonotneedtoadjustthosebeans,butwehavethepossibilitytodosowhichgivesusagreatcustomizationandextensionpoints.TheimportantpartistheendpointadapterdefinitioninsidetheHttpMessageController.Onceaclientrequestwasacceptedtheadapterisresponsibleforgeneratingaproperresponsetotheclient.
YoucanaddthecustomservletcontextasfileresourcetotheCitrusHTTPservercomponent.Justusethecontext-config-locationattributeasfollows:
<citrus-http:serverid="helloHttpServer"port="8080"auto-start="true"context-config-location="classpath:com/consol/citrus/http/custom-servlet-context.xml"resource-base="src/it/resources"/>
CitrusReferenceGuide
260Http
![Page 261: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/261.jpg)
WebSocketsupportTheWebSocketmessageprotocolbuildsontopofHttpstandardandbringsbidirectionalcommunicationtotheHttpclient-serverworld.CitrusisabletosendandreceivemessageswithWebSocketconnectionsasclientandserver.TheHttpserverimplementationisnowabletodefinemultipleWebSocketendpoints.ThenewCitrusWebSocketclientisabletopublishandconsumermessagesviabidirectionalWebSocketprotocol.
ThenewWebSocketsupportislocatedinthemodulecitrus-websocket.ThereforeweneedtoaddthismoduletoourprojectasdependencywhenweareabouttousetheWebSocketfeaturesinCitrus.
<dependency><groupId>com.consol.citrus</groupId><artifactId>citrus-websocket</artifactId><version>2.7.1</version></dependency>
AsCitrusprovidesacustomizedWebSocketconfigurationschemafortheSpringapplicationcontextconfigurationfileswehavetoaddnametothetoplevelbeanselement.Simplyincludethewebsocket-confignamespaceintheconfigurationXMLfilesasfollows.
<beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:citrus="http://www.citrusframework.org/schema/config"xmlns:citrus-websocket="http://www.citrusframework.org/schema/websocket/config"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.citrusframework.org/schema/confighttp://www.citrusframework.org/schema/config/citrus-config.xsdhttp://www.citrusframework.org/schema/websocket/confighttp://www.citrusframework.org/schema/websocket/config/citrus-websocket-config.xsd"
[...]
</beans>
CitrusReferenceGuide
261HttpWebsockets
![Page 262: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/262.jpg)
NowourprojectisreadytousetheCitrusWebSocketsupport.FirstofallletussendamessageviaWebSocketconnectiontosomeserver.
WebSocketclient
OntheclientsideCitrusoffersaclientcomponentthatgoesdirectlytotheSpringbeanapplicationcontext.Theclientneedsaserverendpointuri.ThisisaWebSocketprotocolendpointuri.
<citrus-websocket:clientid="helloWebSocketClient"url="http://localhost:8080/hello"timeout="5000"/>
Theurldefinestheendpointtosendmessagesto.TheserverhastobeaWebSocketreadywebserverthatsupportsHttpconnectionupgradeforWebSocketprotocols.WebSocketbyitsnatureisanasynchronousbidirectionalprotocol.Thismeansthattheconnectionbetweenclientandserverremainsopenandbothserverandclientcansendandreceivemessages.SowhentheCitrusclientiswaitingforamessageweneedatimeoutthatstopstheasynchronouswaiting.Thereceivingtestactionandthetestcasewillfailwhensuchatimeoutisraised.
TheWebSocketclientwillautomaticallyopenaconnectiontotheserverandaskforaconnectionupgradetoWebSocketprotocol.Thishandshakeisdoneoncewhentheconnectiontotheserverisestablished.Afterthattheclientcanpushmessagestotheserverandontheothersidetheservercanpushmessagestotheclient.Nowletsfirstpushsomemessagestotheserver:
<sendendpoint="helloWebSocketClient"><message><payload><TestMessage><Text>HelloWebSocketServer</Text></TestMessage></payload></message></send>
Theconnectionhandshakeandtheconnectionupgradeisdoneautomaticallybytheclient.Afterthatthemessageispushedtotheserver.AsWebSocketisabidirectionalprotocolwecanalsoreceivemessagesontheWebSocketclient.Thesemessagesarepushedfromservertoallconnectedclients.
CitrusReferenceGuide
262HttpWebsockets
![Page 263: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/263.jpg)
<receiveendpoint="helloWebSocketClient"><message><payload><TestMessage><Text>HelloWebSocketClient</Text></TestMessage></payload></message></receive>
Wejustusetheverysameclientendpointcomponentinamessagereceiveaction.Theclientwillwaitformessagesfromtheserverandoncereceivedperformthewellknownmessagevalidation.HereweexpectsomeXMLmessagepayload.ThiscompletestheclientsideasweareabletopushandconsumermessagesviaWebSocketconnections.
TipUptonowwehaveusedstaticWebSocketendpointURIsinourclientcomponentconfigurations.ThiscanbedonewithamorepowerfuldynamicendpointURIinWebSocketclient.SimilartotheendpointresolvingmechanisminSOAPyoucandynamicallysetthecalledendpointuriattestruntimethroughmessageheadervalues.BydefaultCitruswillcheckaspecificheaderentryfordynamicendpointURIwhichissimplydefinedforeachmessagesendingactioninsidethetest.
ThedynamicEndpointResolverbeanmustimplementtheEndpointUriResolverinterfaceinordertoresolvedynamicendpointurivalues.Citrusoffersadefaultimplementation,theDynamicEndpointUriResolver,whichusesaspecificmessageheaderforsettingdynamicendpointuri.Themessageheaderneedstospecifytheheadercitrus_endpoint_uriwithavalidrequesturi.
<header><elementname="citrus_endpoint_uri"value="ws://localhost:8080/customers/$customerId"</header>
Thespecificsendactionabovewillsenditsmessagetothedynamicendpoint(ws://localhost:8080/customers/$customerId)whichissetintheheadercitrus_endpoint_uri.
WebSocketserverendpoints
CitrusReferenceGuide
263HttpWebsockets
![Page 264: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/264.jpg)
OntheserversideCitrushasaHttpserverimplementationthatwecaneasilystartduringtestruntime.TheHttpserveracceptsconnectionsfromclientsandalsosupportsWebSocketupgradestrategies.ThismeansclientscanaskforaupgradetotheWebSocketstandard.InthishandshaketheserverwillupgradetheconnectiontoWebSocketandafterwardsclientandservercanexchangemessagesoverthisconnection.Thismeanstheconnectioniskeptaliveandmultiplemessagescanbeexchanged.LetsseehowWebSocketendpointsareaddedtoaHttpservercomponentinCitrus.
<citrus-websocket:serverid="helloHttpServer"port="8080"auto-start="true"resource-base="src/it/resources"><citrus-websocket:endpoints><citrus-websocket:endpointref="websocket1"/><citrus-websocket:endpointref="websocket2"/></citrus-websocket:endpoints></citrus-websocket:server>
<citrus-websocket:endpointid="websocket1"path="/test1"/><citrus-websocket:endpointid="websocket2"path="/test2"timeout="10000"/>
TheembeddedJettyWebSocketservercomponentinCitrusnowisabletodefinemultipleWebSocketendpoints.TheWebSocketendpointsmatchtoarequestpathontheserverandarereferencedbyauniqueid.EachWebSocketendpointcanfollowindividualtimeoutsettings.Inatestwecanusetheseendpointsdirectlytoreceivemessages.
<testcasename="httpWebSocketServerTest"><actions><receiveendpoint="websocket1"><message><data>[...]</data></message></receive>
<sendendpoint="websocket1"><message><data>[...]</data></message></send>
CitrusReferenceGuide
264HttpWebsockets
![Page 265: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/265.jpg)
</actions></testcase>
Asyoucanseewereferencetheendpointidinbothreceiveandsendactions.EachWebSocketendpointholdsoneormoreopenconnectionstoitsclients.Eachmessagethatissentispushedtoallconnectedclients.EachclientcansendmessagestotheWebSocketendpoint.
TheWebSocketendpointcomponenthandlesconnectionhandshakesautomaticallyandcachesallopensessionsinmemory.Bydefaultallconnectedclientswillreceivethemessagespushedfromserver.Thisisdonecompletelybehindthescenes.TheCitrusserverisabletohandlemultipleWebSocketendpointswithdifferentclientsconnectedtoitatthesametime.ThisiswhywehavetochoosetheWebSocketendpointontheserverbyitsidentifierwhensendingandreceivingmessages.
WiththisWebSocketendpointswechangetheCitrusserverbehaviorsothatclientscanupgradetoWebSocketconnection.Nowwehaveabidirectionalconnectionwheretheservercanpushmessagestotheclientandviceversa.
WebSocketheaders
TheWebSocketstandarddefinessomedefaultheaderstouseduringconnectionupgrade.Theseheadersaremadeavailabletothetestcaseinbothdirections.CitruswillhandletheseheadervalueswithspecialcarewhenWebSocketsupportisactivatedonaserverorclient.NowWebSocketmessagescanalsobesplitintomultiplepieces.Eachmessagepartispushedseparatelytotheserverbutstillisconsideredtobeasinglemessagepayload.TheserverhastocollectandaggregateallmessagesuntilaspecialmessageheaderisLastissetinoneofthemessageparts.
TheCitrusWebSocketclientcanslicemessagesintoseveralparts.
<sendendpoint="webSocketClient"><messagetype="json"><data>["event":"client_message_1","timestamp":"citrus:currentDate()",</data></message><header><elementname="citrus_websocket_is_last"value="false"/>
CitrusReferenceGuide
265HttpWebsockets
![Page 266: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/266.jpg)
</header></send>
<sleepmilliseconds="500"/>
<sendendpoint="webSocketClient"><messagetype="json"><data>"event":"client_message_2","timestamp":"citrus:currentDate()"]</data></message><header><elementname="citrus_websocket_is_last"value="true"/></header></send>
ThetestabovehastwoseparatesendoperationsbothsendingtoaWebSocketendpoint.Thefirstsendingactionsetstheheadercitrus_websocket_is_lasttofalsewhichindicatesthatthemessageisnotcompleteyet.The2ndsendactionpushestherestofthemessagetotheserverandsetthecitrus_websocket_is_lastheadertotrue.Nowtheserverisabletoaggregatethemessagepiecestoasinglemessagepayload.TheresultisavalidaJSONarraywithbotheventsinit.
["event":"client_message_1","timestamp":"2015-01-01","event":"client_message_2","timestamp":"2015-01-01"]
NowtheserverpartinCitrusisabletohandletheseslicedmessages,too.Theserverwillautomaticallyaggregatethosemessagepartsbeforepassingittothetestcaseforvalidation.
CitrusReferenceGuide
266HttpWebsockets
![Page 267: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/267.jpg)
SOAPWebServicesSOAPWebServicesoverHTTPisawidelyusedcommunicationscenarioinmodernenterpriseapplications.ASOAPWebServiceclientispostingaSOAPrequestviaHTTPtoaserver.SOAPviaHTTPisasynchronousmessageprotocolbydefaultsotheclientiswaitingsynchronouslyfortheresponsemessage.CitrusprovidesbothSOAPclientandservercomponentsinordertomeetbothdirectionsofthisscenario.ThecomponentsusedareverysimilartotheHTTPcomponentsthatwerehavediscussedinthesectionsbefore.
NoteTheSOAPWebServicecomponentsinCitrusarekeptinaseparateMavenmodule.SoyoushouldaddthemoduleasMavendependencytoyourprojectaccordingly.
<dependency><groupId>com.consol.citrus</groupId><artifactId>citrus-ws</artifactId><version>2.7.1</version></dependency>
InordertousetheSOAPWebServicesupportyouneedtoincludethespecificXMLconfigurationschemaprovidedbyCitrus.SeefollowingXMLdefinitiontofindouthowtoincludethecitrus-wsnamespace.
<beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:citrus="http://www.citrusframework.org/schema/config"xmlns:citrus-ws="http://www.citrusframework.org/schema/ws/config"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.citrusframework.org/schema/confighttp://www.citrusframework.org/schema/config/citrus-config.xsdhttp://www.citrusframework.org/schema/ws/confighttp://www.citrusframework.org/schema/ws/config/citrus-ws-config.xsd">
[...]
</beans>
CitrusReferenceGuide
267Soap
![Page 268: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/268.jpg)
Nowyouarereadytousethecustomizedsoapconfigurationelements-allusingthecitrus-wsprefix-inyourSpringconfiguration.
SOAPclient
CitrusisabletoformaproperSOAPrequestinordertopassittotheserverviaHTTPandvalidatetherespectiveSOAPresponsemessage.LetusseehowamessageclientforSOAPlookslikeintheSpringconfiguration:
<citrus-ws:clientid="soapClient"request-url="http://localhost:8090/test"timeout="60000"/>
Theclientcomponentusestherequest-urlinordertoaccesstheserverresource.TheclientwillautomaticallybuildaproperSOAPrequestmessageincludingtheSOAPenvelope,SOAPheaderandthemessagepayloadasSOAPbody.ThismeansthatyouasatesterdonotcareaboutSOAPenvelopespecificlogicinthetestcase.TheclientendpointcomponentsavesthesynchronousSOAPresponsesothetestcasecanreceivethismessagewithanormalreceivetestaction.
IndetailyouasatesterjustsendandreceiveusingthesameclientendpointreferencejustasyouwoulddowithasynchronousJMSorchannelcommunication.IncasenoresponsemessageisavailableintimeaccordingtothetimeoutsettingsCitrusraisesatimeouterrorandthetestwillfail.
ImportantTheSOAPclientcomponentusesaSoapMessageFactoryimplementationinordertocreatetheSOAPmessages.ThisisaSpringbeanaddedtotheCitrusSpringapplicationcontext.Springoffersseveralreferenceimplementationsasmessagefactoriessoyoucanchooseoneofthem(e.g.forSOAP1.1or1.2implementations).
<!--DefaultSOAPMessageFactory(SOAP1.1)--><beanid="messageFactory"class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory"/>
<!--SOAP1.2MessageFactory--><beanid="soap12MessageFactory"class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory"<propertyname="soapVersion"><util:constantstatic-field="org.springframework.ws.soap.SoapVersion.SOAP_12"/></property></bean>
CitrusReferenceGuide
268Soap
![Page 269: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/269.jpg)
BydefaultCitruswillsearchforabeanwithid'messageFactory'.IncaseyouintendtousedifferentidentifiersyouneedtotelltheSOAPclientcomponentwhichmessagefactorytouse:
<citrus-ws:clientid="soapClient"request-url="http://localhost:8090/test"message-factory="soap12MessageFactory"/>
TipUptonowwehaveusedastaticendpointrequesturlfortheSOAPmessagesender.Besidesthatwecanusedynamicendpointuriinconfiguration.Wejustuseanendpointuriresolverinsteadofthestaticrequesturllikethis:
<citrus-ws:clientid="soapClient"endpoint-resolver="dynamicEndpointResolver"message-factory="soap12MessageFactory"/>
<beanid="dynamicEndpointResolver"class="com.consol.citrus.endpoint.resolver.DynamicEndpointUriResolver"/>
ThedynamicEndpointResolverbeanmustimplementtheEndpointUriResolverinterfaceinordertoresolvedynamicendpointurivalues.Citrusoffersadefaultimplementation,theDynamicEndpointUriResolver,whichusesaspecificmessageheaderforsettingthedynamicendpointuriforeachmessage.Themessageheaderneedstospecifytheheadercitrus_endpoint_uriwithavalidrequesturi.Justlikethis:
<header><elementname="citrus_endpoint_uri"value="http://localhost:$port/$context"/></header>
Asyoucanseeyoucanusedynamictestvariablestheninordertobuildtherequesturitouse.TheSOAPclientevaluatestheendpointuriheaderandsendsthemessagetothisserverresource.Youcanuseadifferenturivaluethenindifferenttestcasesandsendactions.
SOAPclientinterceptors
Theclientcomponentisabletoaddcustominterceptorsthatparticipateintherequest/responseprocessing.Theinterceptorsneedtoimplementthecommoninterfaceorg.springframework.ws.client.support.interceptor.ClientInterceptor.
CitrusReferenceGuide
269Soap
![Page 270: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/270.jpg)
<citrus-ws:clientid="secureSoapClient"request-url="http://localhost:8080/services/ws/todolist"interceptors="clientInterceptors"/>
<util:listid="clientInterceptors"><beanclass="org.springframework.ws.soap.security.wss4j.Wss4jSecurityInterceptor"><propertyname="securementActions"value="TimestampUsernameToken"/><propertyname="securementUsername"value="admin"/><propertyname="securementPassword"value="secret"/></bean><beanclass="com.consol.citrus.ws.interceptor.LoggingClientInterceptor"/></util:list>
ThesampleaboveaddsWss4JWsSecurityinterceptorsinordertoaddsecurityconstraintstotherequestmessages.
NoteWhencustomizingtheinterceptorchainalldefaultinterceptors(likelogginginterceptor)arelost.Youneedtoaddtheseinterceptorsexlicitlyasshownwiththecom.consol.citrus.ws.interceptor.LoggingClientInterceptorwhichisabletologrequest/responsemessagesduringcommunication.
SOAPserver
Everyclientneedaservertotalkto.WhenreceivingSOAPmessageswerequireawebserverinstancelisteningonaport.CitrusisusinganembeddedJettyserverinstanceincombinationwiththeSpringWebServiceAPIinordertoacceptSOAPrequestcallsasaserver.SeehowtheCitrusSOAPserverisconfiguredintheSpringconfiguration.
<citrus-ws:serverid="helloSoapServer"port="8080"auto-start="true"resource-base="src/it/resources"/>
Theservercomponentisabletostartautomaticallywhenapplicationstartsup.Intheexampleabovetheserverislisteningforrequestsonport8080.ThissetupusesthestandardconnectorconfigurationfortheJettyserver.FordetailedcustomizationtheCitrusJettyserverconfigurationalsosupportsexplicitconnectorconfigurations(@connectorand@connectorsattributes).FormoreinformationpleaseseetheJettyconnectordocumentation.
Testcasesinteractwiththisserverinstanceviamessagechannelsbydefault.Theservercomponentprovidesaninboundchannelthatholdsincomingrequestmessages.Thetestcasecanreceivethoserequestsfromthechannelwithanormalreceivetest
CitrusReferenceGuide
270Soap
![Page 271: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/271.jpg)
action.InasecondstepthetestcasecanprovideasynchronousresponsemessageasreplywhichwillbeautomaticallysentbacktothecallingSOAPclientasresponse.
Thefigureaboveshowsthebasicsetupwithinboundchannelandreplychannel.Youasatestershouldnotworryaboutthistomuch.Bydefaultyouasatesterjustusetheserverassynchronousendpointinyourtestcase.Thismeansthatyousimplyreceiveamessagefromtheserverandsendaresponseback.
<testcasename="soapServerTest"><actions><receiveendpoint="helloSoapServer"><message><data>[...]</data></message></receive>
<sendendpoint="helloSoapServer"><message><data>[...]</data></message></send></actions></testcase>
Asyoucanseewereferencetheserveridinbothreceiveandsendactions.TheCitrusserverinstancewillautomaticallysendtheresponsebacktothecallingclient.InmostcasesthisiswhatyouneedtosimulateaSOAPserverinstanceinCitrus.Ofcoursewehavesomemorecustomizationpossibilitiesthatwewillgooverlateron.ThiscustomizationsareoptionalsoyoucanalsoskipthenextdescriptiononendpointadaptersifyouarehappywithjustwhatyouhavelearnedabouttheSOAPservercomponentinCitrus.
JustliketheHTTPservercomponenttheSOAPservercomponentbydefaultusesthechannelendpointadapterinordertoforwardallincomingrequeststoaninmemorymessagechannel.Thisisdonecompletelybehindthescenes.TheCitrusconfiguration
CitrusReferenceGuide
271Soap
![Page 272: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/272.jpg)
hasbecomealoteasierheresoyoudonothavetoconfigurethisbydefault.Whennothingelseissetthetestcasedoesnotworryaboutthatsettingsontheserverandjustusestheserveridreferenceassynchronousendpoint.
TipThedefaultchannelendpointadapterautomaticallycreatesaninboundmessagechannelwhereincomingmessagesarestoredtointernally.Soifyouneedtocleanupaserverthathasalreadystoredsomeincomingmessagesyoucandothiseasilybypurgingtheinternalmessagechannel.ThemessagechannelfollowsanamingconventionserverName.inboundwhereserverNameistheSpringbeannameoftheCitrusserverendpointcomponent.Ifyoupurgethisinternalchannelinabeforetestnatureyouaresurethatobsoletemessagesonaserverinstancegetpurgedbeforeeachtestisexecuted.
HoweverwedonotwanttoloosethegreatextendabilityandcustomizingcapabilitiesoftheCitrusservercomponent.ThisiswhyyoucanoptionallydefinetheendpointadapterimplementationusedbytheCitrusSOAPserver.Weprovideseveralmessageendpointadapterimplementationsfordifferentsimulationstrategies.WiththeseendpointadaptersyoushouldbeabletogenerateproperSOAPresponsemessagesfortheclientinvariousways.Beforewehaveacloserlookatthedifferentadapterimplementationswewanttoshowhowyoucansetacustomendpointadapterontheservercomponent.
<citrus-ws:serverid="helloSoapServer"port="8080"auto-start="true"endpoint-adapter="emptyResponseEndpointAdapter"resource-base="src/it/resources"/>
<citrus:empty-response-adapterid="emptyResponseEndpointAdapter"/>
WiththisendpointadapterconfigurationabovewechangetheCitrusserverbehaviorfromscratch.NowtheserverautomaticallysendsbackanemptySOAPresponsemessageeverytime.SettingacustomendpointadapterimplementationwithcustomlogiciseasyasdefiningacustomendpointadapterSpringbeanandreferenceitintheserverattribute.Youcanreadmoreaboutendpointadaptersinendpoint-adapter.
SOAPsendandreceive
Citrusprovidestestactionsforsendingandreceivingmessagesofallkind.Differentmessagecontentanddifferentmessagetransportsareavailabletothesesendandreceiveactions.WhenusingSOAPmessagetransportwemightneedtosetspecial
CitrusReferenceGuide
272Soap
![Page 273: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/273.jpg)
informationonthatmessages.ThesearespecialSOAPheaders,SOAPfaultsandsoon.SowehavecreatedaspecialSOAPnamespaceforallyourSOAPrelatedsendandreceiveoperationsinaXMLDSLtest:
<spring:beansxmlns="http://www.citrusframework.org/schema/testcase"xmlns:spring="http://www.springframework.org/schema/beans"xmlns:ws="http://www.citrusframework.org/schema/ws/testcase"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.citrusframework.org/schema/testcasehttp://www.citrusframework.org/schema/testcase/citrus-testcase.xsdhttp://www.citrusframework.org/schema/ws/testcasehttp://www.citrusframework.org/schema/ws/testcase/citrus-ws-testcase.xsd">
Onceyouhaveaddedthewsnamespacefromabovetoyourtestcaseyouarereadytousespecialsendandreceiveoperationsinthetest.
XMLDSL
<ws:sendendpoint="soapClient"soap-action="MySoapService/sayHello"><message>[...]</message></ws:send>
<ws:receiveendpoint="soapServer"soap-action="MySoapService/sayHello"><message>[...]</message></ws:receive>
Thespecialnamespacecontainsfollowingelements:
send:SpecialsendoperationforsendingoutSOAPmessagecontent.receive:SpecialreceiveoperationforvalidatingSOAPmessagecontent.send-fault:SpecialsendoperationforsendingoutSOAPfaultmessagecontent.assert-fault:SpecialassertionoperationforexpectingaSOAPfaultmessageasresponse.
ThespecialSOAPrelatedsendandreceiveactionscancoexistwithnormalCitrusactions.Infactyoucanmixthoseactiontypesasyouwantinsideofatestcase.AlltestactionsthatworkwithSOAPmessagecontentonclientandserversideshouldusethisspecialnamespace.
CitrusReferenceGuide
273Soap
![Page 274: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/274.jpg)
InJavaDSLwehavesomethingsimilartothat.TheJavaDSLprovidesspecialSOAPrelatedfeatureswhencallingthesoap()method.WithafluentAPIyouareabletothensendandreceiveSOAPmessagecontentasclientandserver.
JavaDSL
@CitrusTestpublicvoidsoapTest()
soap().client("soapClient").send().soapAction("MySoapService/sayHello").payload("...");
soap().client("soapClient").receive().payload("...");
InthefollowingsectionstheSOAPrelatedcapabilitiesarediscussedinmoredetail.
SOAPheaders
SOAPdefinesseveralheadervariationsthatwediscussinthefollowingsections.FirstofallwedealwiththespecialSOAPactionheader.IncaseweneedtosetthisSOAPactionheaderwesimplyneedtousethespecialsoap-actionattributeinourtest.ThespecialheaderkeyincombinationwithaunderlyingSOAPclientendpointcomponentconstructstheSOAPactionintheSOAPmessage.
XMLDSL
<ws:sendendpoint="soapClient"soap-action="MySoapService/sayHello"><message>[...]</message></ws:send>
<ws:receiveendpoint="soapServer"soap-action="MySoapService/sayHello"><message>[...]</message></ws:receive>
JavaDSL
CitrusReferenceGuide
274Soap
![Page 275: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/275.jpg)
@CitrusTestpublicvoidsoapActionTest()
soap().client("soapClient").send().soapAction("MySoapService/sayHello").payload("...");
soap().server("soapClient").receive().soapAction("MySoapService/sayHello").payload("...");
TheSOAPactionheaderisaddedtothemessagebeforesendingandvalidatedwhenusedinareceiveoperation.
NoteThesoap-actionattributeisdefinedinthespecialSOAPnamespaceinCitrus.WerecommendtousethisnamespaceforallyoursendandreceiveoperationsthatdealwithSOAPmessagecontent.HoweveryoucanalsosetthespecialSOAPactionheaderwhennotusingthespecialSOAPnamespace:Justsetthisheaderinyourtestaction:
<header><elementname="citrus_soap_action"value="sayHello"/></header>
SecondlyaSOAPmessageisabletocontaincustomizedSOAPheaders.Thesearekey-valuepairswherethekeyisaqualifiedname(QName)andthevalueanormalStringvalue.
<header><elementname="http://www.consol.de/sayHelloh1:Operation"value="sayHello"/><elementname="http://www.consol.de/sayHelloh1:Request"value="HelloRequest"/></header>
ThekeyisdefinedasqualifiedQNamecharactersequencewhichhasamandatoryXMLnamespaceandaprefixalongwithaheadername.LastnotleastaSOAPheadercancontainwholeXMLfragmentvalues.ThenextexampleshowshowtosettheseXMLfragmentsasSOAPheaderinCitrus:
<header><data><![CDATA[<Userxmlns="http://www.consol.de/schemas/sayHello">
CitrusReferenceGuide
275Soap
![Page 276: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/276.jpg)
<UserId>123456789</UserId><Handshake>S123456789</Handshake></User>]]></data></header>
YoucanalsouseexternalfileresourcestosetthisSOAPheaderXMLfragmentasshowninthislastexamplecode:
<header><resourcefile="classpath:request-soap-header.xml"/></header>
ThiscompletestheSOAPheaderpossibilitiesforsendingSOAPmessageswithCitrus.OfcourseyoucanalsousethesevariantsinSOAPmessageheadervalidation.YoudefineexpectedSOAPheaders,SOAPactionandXMLfragmentsandCitruswillmatchincomingrequesttothat.Justusecitrus_soap_actionheaderkeyinyourreceivingmessageactionandyouvalidatethisSOAPheaderaccordingly.
WhenvalidatingSOAPheaderXMLfragmentsyouneedtodefinethewholeXMLheaderfragmentasexpectedheaderdatalikethis:
<receiveendpoint="soapMessageEndpoint"><message><data><![CDATA[<ResponseMessagexmlns="http://citrusframework.org/schema"><resultCode>OK</resultCode></ResponseMessage>]]></data></message><header><data><![CDATA[<SOAP-ENV:Headerxmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><customHeaderxmlns="http://citrusframework.org/headerschema"><correlationId>$correlationId</correlationId><applicationId>$applicationId</applicationId><trackingId>$trackingId</trackingId><serviceId>$serviceId</serviceId><interfaceVersion>1.0</interfaceVersion><timestamp>@ignore@</timestamp></customHeader>
CitrusReferenceGuide
276Soap
![Page 277: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/277.jpg)
</SOAP-ENV:Header>]]></data><elementname="citrus_soap_action"value="doResponse"/></header></receive>
AsyoucanseetheSOAPXMLheadervalidationcancombineheaderelementandXMLfragmentvalidation.ThisisalsolikelytobeusedwhendealingwithWS-Securitymessageheaders.
SOAPHTTPmimeheaders
BesidestheSOAPspecificheaderelementstheHTTPmimeheaders(e.g.Content-Type,Content-Length,Authorization)mightbecandidatesforvalidation,too.WhenusingHTTPastransportlayertheSOAPmessagemaydefinethosemimeheaders.Thetesterisabletosendandvalidatetheseheadersinsidethetestcase,althoughtheseHTTPheadersarelocatedoutsideoftheSOAPenvelope.LetusfirstofallspeakaboutvalidatingtheHTTPmimeheaders.Thisfeatureisnotenabledbydefault.WehaveenablethisinourSOAPserverconfiguration.
<citrus-ws:serverid="helloSoapServer"port="8080"auto-start="true"handle-mime-headers="true"resource-base="src/it/resources"/>
WiththisconfigurationCitruswillhandleallavailablemimeheadersandpassthosetothetestcasefornormalheadervalidation.
<ws:receiveendpoint="helloSoapServer"><message><payload><SoapMessageRequestxmlns="http://www.consol.de/schemas/sample.xsd"><Operation>Validatemimeheaders</Operation></SoapMessageRequest></payload></message><header><elementname="Content-Type"value="text/xml;charset=utf-8"/></header></ws:receive>
CitrusReferenceGuide
277Soap
![Page 278: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/278.jpg)
ThevalidationoftheseHTTPmimeheadersisasusualnowthatwehaveenabledthemimeheaderhandlingintheSOAPserver.ThetransportHTTPheadersareavailableintheheaderjustlikethenormalSOAPheaderelementsdo.Soyoucanvalidatetheheadersasusual.
SomuchforreceivingandvalidatingHTTPmimemessageheaderswithSOAPcommunication.Nowwewanttosendspecialmimeheadersonclientside.Weoverwriteoraddmimeheaderstooursendingaction.Wemarksomeheaderswithfollowingprefix"citrushttp".ThistellstheSOAPclienttoaddtheseheaderstotheHTTPheadersectionoutsidetheSOAPenvelope.KeepinmindthatheaderelementswithoutthisprefixgorightintotheSOAPheadersectionbydefault.
<ws:sendendpoint="soapClient">[...]<header><elementname="citrus_http_operation"value="foo"/></header>[...]</ws:send>
ThelistingabovedefinesaHTTPmimeheaderoperation.TheheaderprefixcitrushttpiscutoffbeforetheheadergoesintotheHTTPheadersection.Withthisfeaturewecandecidewhereexactlyourheaderinformationislocatedinourresultingclientmessage.
SOAPEnvelopehandling
BydefaultCitruswillremovetheSOAPenvelopeinmessageconverter.FollowingfromthattheCitrustestcaseisindependentfromSOAPmessageformatsandisnotbotheredwithhandlingofSOAPenvelopeatall.ThisisgreatinmostcasesbutsometimesitmightbemandatorytoalsoseethewholeSOAPenvelopeinsidethetestcasereceiveaction.ThereforeyoucankeeptheSOAPenvelopeforincomingmessagesbyconfigurationontheSOAPserverside.
<citrus-ws:serverid="helloSoapServer"port="8080"auto-start="true"keep-soap-envelope="true"/>
WiththisconfigurationCitruswillhandleallavailablemimeheadersandpassthosetothetestcasefornormalheadervalidation.
CitrusReferenceGuide
278Soap
![Page 279: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/279.jpg)
<ws:receiveendpoint="helloSoapServer"><message><payload><SOAP-ENV:Envelopexmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header/><SOAP-ENV:Body><SoapMessageRequestxmlns="http://www.consol.de/schemas/sample.xsd"><Operation>Validatemimeheaders</Operation></SoapMessageRequest></SOAP-ENV:Body></SOAP-ENV:Envelope></payload></message></ws:receive>
SonowyouareabletovalidatethewholeSOAPenvelopeasis.Thismightbeofinterestinveryspecialcases.AsmentionedbydefaulttheCitrusserverwillautomaticallyremovetheSOAPenvelopeandtranslatetheSOAPbodytothemessagepayloadforstraightforwardvalidationinsidethetestcases.
SOAPserverinterceptors
TheCitrusSOAPserversupportstheconceptofinterceptorsinordertoaddcustomlogictotherequest/responseprocessingsteps.Theinterceptorsneedtoimplementacommoninterface:org.springframework.ws.server.EndpointInterceptor.Weareabletocustomizetheinterceptorchainontheservercomponentasfollows:
<citrus-ws:serverid="secureSoapServer"port="8080"auto-start="true"interceptors="serverInterceptors"/>
<util:listid="serverInterceptors"><beanclass="com.consol.citrus.ws.interceptor.SoapMustUnderstandEndpointInterceptor"><propertyname="acceptedHeaders"><list><value>http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsdSecurity</list></property></bean><beanclass="com.consol.citrus.ws.interceptor.LoggingEndpointInterceptor"/><beanclass="org.springframework.ws.soap.security.wss4j.Wss4jSecurityInterceptor"><propertyname="validationActions"value="TimestampUsernameToken"/><propertyname="validationCallbackHandler"><beanid="passwordCallbackHandler"class="org.springframework.ws.soap.security.wss4j.callback.SimplePasswordValidationCallbackHandler"<propertyname="usersMap">
CitrusReferenceGuide
279Soap
![Page 280: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/280.jpg)
<map><entrykey="admin"value="secret"/></map></property></bean></property></bean></util:list>
ThecustominterceptorsareusedtoenableWsSecurityfeaturesonthesoapservercomponentviaWss4J.
NoteWhencustomizingtheinterceptorchainofthesoapservercomponentalldefaultinterceptors(likelogginginterceptors)arelost.Youcanseethatwehadtoaddthecom.consol.citrus.ws.interceptor.LoggingEndpointInterceptorexplicitlyinordertologrequest/responsemessagesfortheservercommunication.
SOAP1.2
BydefaultCitruscomponentsuseSOAP1.1version.FortunatelySOAP1.2issupportedsameway.AswealreadymentionedbeforetheCitrusSOAPcomponentsdouseaSOAPmessagefactoryforcreatingmessagesinSOAPformat.
<!--SOAP1.1MessageFactory--><beanid="soapMessageFactory"class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory"<propertyname="soapVersion"><util:constantstatic-field="org.springframework.ws.soap.SoapVersion.SOAP_11"/></property></bean>
<!--SOAP1.2MessageFactory--><beanid="soap12MessageFactory"class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory"<propertyname="soapVersion"><util:constantstatic-field="org.springframework.ws.soap.SoapVersion.SOAP_12"/></property></bean>
AsyoucanseetheSOAPmessagefactorycaneithercreateSOAP1.1orSOAP1.2messages.ThisishowCitruscancreatebothSOAP1.1andSOAP1.2messages.Ofcourseyoucanhavemultiplemessagefactoriesconfiguredinyourproject.JustsetthemessagefactoryonaWebServiceclientorservercomponentinordertodefinewhichversionshouldbeused.
CitrusReferenceGuide
280Soap
![Page 281: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/281.jpg)
<citrus-ws:clientid="soap12Client"request-url="http://localhost:8080/echo"message-factory="soap12MessageFactory"timeout="1000"/>
<citrus-ws:serverid="soap12Server"port="8080"auto-start="true"root-parent-context="true"message-factory="soap12MessageFactory"/>
BydefaultCitruscomponentsdoconnectwithamessagefactorycalledmessageFactorynomatterwhatSOAPversionthisfactoryisusing.
SOAPfaults
SOAPfaultsdescribeafailedcommunicationinSOAPWebServicesworld.CitrusisabletosendandreceiveSOAPfaultmessages.OnserversideCitruscansimulateSOAPfaultswithfault-code,fault-reason,fault-actorandfault-detail.OnclientsideCitrusisabletohandleandvalidateSOAPfaultsinresponsemessages.ThenextsectiondescribeshowtodealwithSOAPfaultsinCitrus.
SendSOAPfaults
AsCitrussimulatesSOAPserverendpointsyoualsoneedtothinkaboutsendingaSOAPfaulttothecallingclient.IncaseCitrusreceivesaSOAPrequestasaserveryoucanrespondwithaproperSOAPfaultifnecessary.
Pleasekeepinmindthatweusethecitrus-wsextensionforsendingSOAPfaultsinourtestcase,asshowninthisverysimpleexample:
XMLDSL
<ws:send-faultendpoint="helloSoapServer"><ws:fault><ws:fault-code>http://www.citrusframework.org/faultscitrus:TEC-1000</ws:fault-code><ws:fault-string>Invalidrequest</ws:fault-string><ws:fault-actor>SERVER</ws:fault-actor><ws:fault-detail><![CDATA[<FaultDetailxmlns="http://www.consol.de/schemas/sayHello.xsd"><MessageId>$messageId</MessageId><CorrelationId>$correlationId</CorrelationId><ErrorCode>TEC-1000</ErrorCode>
CitrusReferenceGuide
281Soap
![Page 282: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/282.jpg)
<Text>Invalidrequest</Text></FaultDetail>]]></ws:fault-detail></ws:fault><ws:header><ws:elementname="citrus_soap_action"value="sayHello"/></ws:header></ws:send-fault>
TheexamplegeneratesasimpleSOAPfaultthatissentbacktothecallingclient.Thefault-actorandthefault-detailelementsareoptional.SamewiththesoapactiondeclaredinthespecialCitrusheadercitrus_soap_action.Inthesampleabovethefault-detaildataisplacedinlineasXMLdata.Asanalternativetothatyoucanalsosetthefault-detailviaexternalfileresource.JustusethefileattributeasfaultdetailinsteadoftheinlineCDATAdefinition.
XMLDSL
<ws:send-faultendpoint="helloSoapServer"><ws:fault><ws:fault-code>http://www.citrusframework.org/faultscitrus:TEC-1000</ws:fault-code><ws:fault-string>Invalidrequest</ws:fault-string><ws:fault-actor>SERVER</ws:fault-actor><ws:fault-detailfile="classpath:myFaultDetail.xml"/></ws:fault><ws:header><ws:elementname="citrus_soap_action"value="sayHello"/></ws:header></ws:send-fault>
ThegeneratedSOAPfaultlookslikefollows:
HTTP/1.1500InternalServerErrorAccept:text/xml,text/html,image/gif,image/jpeg,*;q=.2,*/*;q=.2SOAPAction:"sayHello"Content-Type:text/xml;charset=utf-8Content-Length:680Server:Jetty(7.0.0.pre5)
<SOAP-ENV:Envelopexmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header/><SOAP-ENV:Body><SOAP-ENV:Fault>
CitrusReferenceGuide
282Soap
![Page 283: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/283.jpg)
<faultcodexmlns:citrus="http://www.citrusframework.org/faults">citrus:TEC-1000</<faultstringxml:lang="en">Invalidrequest</faultstring><detail><FaultDetailxmlns="http://www.consol.de/schemas/sayHello.xsd"><MessageId>9277832563</MessageId><CorrelationId>4346806225</CorrelationId><ErrorCode>TEC-1000</ErrorCode><Text>Invalidrequest</Text></FaultDetail></detail></SOAP-ENV:Fault></SOAP-ENV:Body></SOAP-ENV:Envelope>
ImportantNoticethatthesendactionusesaspecialXMLnamespace(ws:send).ThiswsnamespacebelongstotheCitrusWebServiceextensionandaddsSOAPspecificfeaturestothenormalsendaction.Whenyouusesuchwsextensionsyouneedtodefinetheadditionalnamespaceinyourtestcase.Thisisusuallydoneintheroot<spring:beans>elementwherewesimplydeclarethecitrus-wsspecificnamespacelikefollows.```xml
###ReceiveSOAPfaults
IncaseyoureceiveSOAPresponsemessagesasaclientendpointyoumayneedtohandleandvalidateSOAPfaultsinerrorsituations.CitruscanvalidateSOAPfaultswithfault-code,fault-actor,fault-stringandfault-detailvalues.
AsaclientwesendoutarequestandreceiveaSOAPfaultasresponse.BydefaulttheclientsendingactioninCitrusthrowsaspecificexceptionwhentheSOAPresponseisaSOAPfaultelement.Thisexceptioniscalled***SoapFaultClientException***comingfromtheSpringAPI.YouasatestercanassertthiskindofexceptioninatestcaseinordertoexpecttheSOAPerror.
**XMLDSL**
```xml<assertclass="org.springframework.ws.soap.client.SoapFaultClientException"><sendendpoint="soapClient"><message><payload><SoapFaultForcingRequestxmlns="http://www.consol.de/schemas/soap"><Message>Thisisinvalid</Message></SoapFaultForcingRequest></payload></message></send></assert>
CitrusReferenceGuide
283Soap
![Page 284: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/284.jpg)
TheSOAPmessagesendingactionissurroundedbyasimpleassertaction.TheassertedexceptionclassistheSoapFaultClientExceptionthatwehavementionedbefore.Thismeansthatthetestexpectstheexceptiontobethrownduringthecommunication.Incasetheexceptionismissingthetestisfails.
SofarwehaveusedtheCitruscorecapabilitiesofassertinganexception.ThisbasicassertiontestactionisnotabletoofferdirectaccesstotheSOAPfault-codeandfault-stringvaluesforvalidation.ThebasicassertactionsimplyhasnoaccesstotheactualSOAPfaultelements.Fortunatelywecanusethecitrus-wsnamespaceagainwhichoffersaspecialassertactionimplementationespeciallydesignedforSOAPfaultsinthiscase.
XMLDSL
<ws:assert-faultfault-code="http://www.citrusframework.org/faultsTEC-1001"fault-string="Invalidrequest">fault-actor="SERVER"><ws:when><sendendpoint="soapClient"><message><payload><SoapFaultForcingRequestxmlns="http://www.consol.de/schemas/soap"><Message>Thisisinvalid</Message></SoapFaultForcingRequest></payload></message></send></ws:when></ws:assert-fault>
ThespecialassertactionoffersseveralattributestovalidatetheexpectedSOAPfault.Namelytheseare"fault-code","fault-string"and"fault-actor".Thefault-codeisdefinedasaQNamestringandismandatoryforthevalidation.Thefaultassertionalsosupportstestvariablereplacementasusual(e.g.fault-code="http://www.citrusframework.org/faults$myFaultCode").
ThetimeyouuseSOAPfaultvalidationyouneedtotellCitrushowtovalidatetheSOAPfaults.CitrusneedsaninstanceofaSoapFaultValitatorthatweneedtoaddtotheSpringapplicationcontext.BydefaultCitrusissearchingforabeanwiththeid'soapFaultValidator'.
<beanid="soapFaultValidator"class="com.consol.citrus.ws.validation.SimpleSoapAttachmentValidator"
CitrusReferenceGuide
284Soap
![Page 285: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/285.jpg)
CitrusoffersseveralreferenceimplementationsfortheseSOAPfaultvalidators.Theseare:
com.consol.citrus.ws.validation.SimpleSoapAttachmentValidatorcom.consol.citrus.ws.validation.SimpleSoapFaultValidatorcom.consol.citrus.ws.validation.XmlSoapFaultValidator
PleaseseetheAPIdocumentationfordetailsontheavailablereferenceimplementations.OfcourseyoucanalsodefineyourownSOAPvalidatorlogic(wouldbegreatifyoucouldshareyourideas!).Inthetestcaseyoucanexplicitlychoosethevalidatortouse:
XMLDSL
<ws:assert-faultfault-code="http://www.citrusframework.org/faultsTEC-1001"fault-string="Invalidrequest"fault-validator="mySpecialSoapFaultValidator">[...]</ws:assert-fault>
ImportantAnotherimportantthingtonoticewhenassertingSOAPfaultsisthefact,thatCitrusneedstohaveaSoapMessageFactoryavailableintheSpringapplicationcontext.IfyoudealwithSOAPmessagingingeneralyouwillalreadyhavesuchabeaninthecontext.
<beanid="messageFactory"class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory"/>
ChooseoneofSpring'sreferenceimplementationsorsomeotherimplementationasSOAPmessagefactory.Citruswillsearchforabeanwithid'messageFactory'bydefault.IncaseyouhaveotherbeanswithdifferentidentifierspleasechoosethemessageFactoryinthetestcaseassertaction:
XMLDSL
<ws:assert-faultfault-code="http://www.citrusframework.org/faultsTEC-1001"fault-string="Invalidrequest"message-factory="mySpecialMessageFactory">[...]</ws:assert-fault>
CitrusReferenceGuide
285Soap
![Page 286: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/286.jpg)
ImportantNoticethewsspecificnamespacethatbelongstotheCitrusWebServiceextensions.Asthews:assertactionusesSOAPspecificfeaturesweneedtorefertothecitrus-wsnamespace.Youcanfindthenamespacedeclarationintherootelementinyourtestcase.```xml
CitrusisalsoabletovalidateSOAPfaultdetails.Seethefollowingexampleforunderstandinghowtodoit:
**XMLDSL**
```xml<ws:assert-faultfault-code="http://www.citrusframework.org/faultsTEC-1001"fault-string="Invalidrequest"><ws:fault-detail><![CDATA[<FaultDetailxmlns="http://www.consol.de/schemas/soap"><ErrorCode>TEC-1000</ErrorCode><Text>Invalidrequest</Text></FaultDetail>]]></ws:fault-detail><ws:when><sendendpoint="soapClient"><message><payload><SoapFaultForcingRequestxmlns="http://www.consol.de/schemas/soap"><Message>Thisisinvalid</Message></SoapFaultForcingRequest></payload></message></send></ws:when></ws:assert-fault>
TheexpectedSOAPfaultdetailcontentissimplyaddedtothews:assertaction.TheSoapFaultValidatorimplementationdefinedintheSpringapplicationcontextisresponsibleforcheckingtheSOAPfaultdetailwithvalidationalgorithm.Thevalidatorimplementationchecksthedetailcontenttomeettheexpectedtemplate.CitrusprovidessomedefaultSoapFaultValidatorimplementations.SupportedalgorithmsarepureStringcomparison(com.consol.citrus.ws.validation.SimpleSoapFaultValidator)aswellasXMLtreewalk-through(com.consol.citrus.ws.validation.XmlSoapFaultValidator).
CitrusReferenceGuide
286Soap
![Page 287: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/287.jpg)
WhenusingtheXMLvalidationalgorithmyouhavethecompletepowerasknownfromnormalmessagevalidationinreceiveactions.Thisincludesschemavalidationorignoringelementsforinstance.Onthefault-detailelementyouareabletoaddsomevalidationsettingssuchasschema-validation=enabled/disabled,customschema-repositoryandsoon.
XMLDSL
<ws:assert-faultfault-code="http://www.citrusframework.org/faultsTEC-1001"fault-string="Invalidrequest"><ws:fault-detailschema-validation="false"><![CDATA[<FaultDetailxmlns="http://www.consol.de/schemas/soap"><ErrorCode>TEC-1000</ErrorCode><Text>Invalidrequest</Text></FaultDetail>]]></ws:fault-detail><ws:when><sendendpoint="soapClient">[...]</send></ws:when></ws:assert-fault>
PleaseseealsotheCitrusAPIdocumentationforavailablevalidatorimplementationsandvalidationalgorithms.
SofarwehaveusedassertactionwrapperinordertocatchSOAPfaultexceptionsandvalidatetheSOAPfaultcontent.NowwehaveanalternativewayofhandlingSOAPfaultsinCitrus.WithexceptionsthesendactionabortsandwedonothaveareceiveactionfortheSOAPfault.ThismightbeinadequateifweneedtovalidatetheSOAPmessagecontent(SOAPHeaderandSOAPBody)comingwiththeSOAPfault.Thereforethewebservicemessagesendercomponentoffersseveralfaultstrategyoptions.InthefollowingwediscussthepropagationofSOAPfaultasmessagestothereceiveactionaswewoulddowithnormalSOAPmessages.
<citrus-ws:clientid="soapClient"request-url="http://localhost:8090/test"fault-strategy="propagateError"/>
CitrusReferenceGuide
287Soap
![Page 288: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/288.jpg)
WehaveconfiguredafaultstrategypropagateErrorsothemessagesenderwillnotraiseclientexceptionsbutinformthereceiveactionwithSOAPfaultmessagecontents.Bydefaultthefaultstrategyraisesclientexceptions(fault-strategy=throwsException).
Sonowthatwedonotraiseexceptionswecanleaveouttheassertactionwrapperinourtest.InsteadwesimplyuseareceiveactionandvalidatetheSOAPfaultlikethis.
<sendendpoint="soapClient"><message><payload><SoapFaultForcingRequestxmlns="http://www.consol.de/schemas/sample.xsd"><Message>Thisisinvalid</Message></SoapFaultForcingRequest></payload></message></send>
<receiveendpoint="soapClient"timeout="5000"><message><payload><SOAP-ENV:Faultxmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><faultcodexmlns:CITRUS="http://citrus.org/soap">CITRUS:$soapFaultCode</faultcode<faultstringxml:lang="en">$soapFaultString</faultstring></SOAP-ENV:Fault></payload></message></receive>
SochoosethepreferredwayofhandlingSOAPfaultseitherbyassertingclientexceptionsorpropagatingfaultmessagestothereceiveactiononaSOAPclient.
MultipleSOAPfaultdetails
SOAPfaultmessagescanholdmultipleSOAPfaultdetailelements.IntheprevioussectionswehaveusedSOAPfaultdetailsinsendingandreceivingactionsassingleelement.InordertomeettheSOAPspecificationCitrusisalsoabletohandlemultipleSOAPfaultdetailelementsinamessage.Youjustusemultiplefault-detailelementsinyourtestactionlikethis:
<ws:send-faultendpoint="helloSoapServer"><ws:fault><ws:fault-code>http://www.citrusframework.org/faultscitrus:TEC-1000</ws:fault-code><ws:fault-string>Invalidrequest</ws:fault-string><ws:fault-actor>SERVER</ws:fault-actor>
CitrusReferenceGuide
288Soap
![Page 289: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/289.jpg)
<ws:fault-detail><![CDATA[<FaultDetailxmlns="http://www.consol.de/schemas/sayHello.xsd"><MessageId>$messageId</MessageId><CorrelationId>$correlationId</CorrelationId><ErrorCode>TEC-1000</ErrorCode><Text>Invalidrequest</Text></FaultDetail>]]></ws:fault-detail><ws:fault-detail><![CDATA[<ErrorDetailxmlns="http://www.consol.de/schemas/sayHello.xsd"><ErrorCode>TEC-1000</ErrorCode></ErrorDetail>]]></ws:fault-detail></ws:fault><ws:header><ws:elementname="citrus_soap_action"value="sayHello"/></ws:header></ws:send-fault>
ThiswillresultinfollowingSOAPenvelopemessage:
HTTP/1.1500InternalServerErrorAccept:text/xml,text/html,image/gif,image/jpeg,*;q=.2,*/*;q=.2SOAPAction:"sayHello"Content-Type:text/xml;charset=utf-8Content-Length:680Server:Jetty(7.0.0.pre5)
<SOAP-ENV:Envelopexmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header/><SOAP-ENV:Body><SOAP-ENV:Fault><faultcodexmlns:citrus="http://www.citrusframework.org/faults">citrus:TEC-1000</<faultstringxml:lang="en">Invalidrequest</faultstring><detail><FaultDetailxmlns="http://www.consol.de/schemas/sayHello.xsd"><MessageId>9277832563</MessageId><CorrelationId>4346806225</CorrelationId><ErrorCode>TEC-1000</ErrorCode><Text>Invalidrequest</Text></FaultDetail><ErrorDetailxmlns="http://www.consol.de/schemas/sayHello.xsd"><ErrorCode>TEC-1000</ErrorCode></ErrorDetail></detail>
CitrusReferenceGuide
289Soap
![Page 290: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/290.jpg)
</SOAP-ENV:Fault></SOAP-ENV:Body></SOAP-ENV:Envelope>
OfcoursewecanalsoexpectseveralfaultdetailelementswhenreceivingaSOAPfault.
XMLDSL
<ws:assert-faultfault-code="http://www.citrusframework.org/faultsTEC-1001"fault-string="Invalidrequest"><ws:fault-detailschema-validation="false"><![CDATA[<FaultDetailxmlns="http://www.consol.de/schemas/soap"><ErrorCode>TEC-1000</ErrorCode><Text>Invalidrequest</Text></FaultDetail>]]></ws:fault-detail><ws:fault-detail><![CDATA[<ErrorDetailxmlns="http://www.consol.de/schemas/soap"><ErrorCode>TEC-1000</ErrorCode></ErrorDetail>]]></ws:fault-detail><ws:when><sendendpoint="soapClient">[...]</send></ws:when></ws:assert-fault>
Asyoucanseewecanindividuallyusevalidationsettingsforeachfaultdetail.Intheexampleabovewedisabledschemavalidationforthefirstfaultdetailelement.
SendHTTPerrorcodeswithSOAP
TheSOAPserverlogicinCitrusisabletosimulatepureHTTPerrorcodessuchas404"Notfound"or500"Internalservererror".ThegoodthingisthattheCitrusserverisabletoreceivearequestforpropervalidationinareceiveactionandthensimulateHTTPerrorsondemand.
CitrusReferenceGuide
290Soap
![Page 291: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/291.jpg)
ThemechanismonHTTPerrorcodesimulationisnotdifferenttotheusualSOAPrequest/responsehandlinginCitrus.Wereceivetherequestasusualandweprovidearesponse.TheHTTPerrorsituationissimulatedaccordingtothespecialHTTPheadercitrus_http_statusintheCitrusSOAPresponsedefinition.Incasethisheaderissettoavalueotherthan200OKtheCitrusSOAPserversendsanemptySOAPresponsewithHTTPerrorstatuscodesetaccordingly.
<receiveendpoint="helloSoapServer"><message><payload><Messagexmlns="http://consol.de/schemas/sample.xsd"><Text>HelloSOAPserver</Text></Message></payload></message></receive>
<sendendpoint="helloSoapServer"><message><data></data></message><header><elementname="citrus_http_status_code"value="500"/></header></send>
TheSOAPresponsemustbeemptyandtheHTTPstatuscodeissettoavalueotherthan200,like500.ThisresultsinaHTTPerrorsenttothecallingclientwitherror500"Internalservererror".
SOAPattachmentsupport
CitrusisabletoaddattachmentstoaSOAPrequestonclientandserverside.AsusualyoucanvalidatetheSOAPattachmentcontentonareceivedSOAPmessage.ThenextchaptersdescribehowtohandleSOAPattachmentsinCitrus.
SendSOAPattachments
AsclientCitrusisabletoaddattachmentstotheSOAPmessage.Ithinkitisbesttogostraightintoanexampleinordertounderstandhowitworks.
<ws:sendendpoint="soapClient"><message>
CitrusReferenceGuide
291Soap
![Page 292: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/292.jpg)
<payload><SoapMessageWithAttachmentxmlns="http://consol.de/schemas/sample.xsd"><Operation>Readtheattachment</Operation></SoapMessageWithAttachment></payload></message><ws:attachmentcontent-id="MySoapAttachment"content-type="text/plain"><ws:resourcefile="classpath:com/consol/citrus/ws/soapAttachment.txt"/></ws:attachment></ws:send>
NoteInthepreviouschaptersyoumayhavealreadynoticedthecitrus-wsnamespacethatstandsfortheSOAPextensionsinCitrus.Pleaseincludethecitrus-wsnamespaceinyourtestcaseasdescribedearlierinthischaptersoyoucanusetheattachmentsupport.
ThespecialsendactionoftheSOAPextensionnamespaceisawareofSOAPattachments.Theattachmentcontentusuallyconsistsofacontent-idacontent-typeandtheactualcontentasplaintextorbinarycontent.InsidethetestcaseyoucanuseexternalfileresourcesorinlineCDATAsectionsfortheattachmentcontent.AsyouarefamiliarwithCitrusyoumayknowthisalreadyfromotheractions.
CitruswillconstructaSOAPmessagewiththeSOAPattachment.Currentlyonlyoneattachmentpermessageissupported.
ReceiveSOAPattachments
WhenCitruscallsSOAPWebServicesasaclientwemayreceiveSOAPresponseswithattachments.ThetestercanvalidatethosereceivedSOAPmessageswithattachmentcontentquiteeasy.Asusualletushavealookatanexamplefirst.
<ws:receiveendpoint="soapClient"><message><payload><SoapMessageWithAttachmentRequestxmlns="http://consol.de/schemas/sample.xsd"><Operation>Readtheattachment</Operation></SoapMessageWithAttachmentRequest></payload></message><ws:attachmentcontent-id="MySoapAttachment"content-type="text/plain"validator="mySoapAttachmentValidator"><ws:resourcefile="classpath:com/consol/citrus/ws/soapAttachment.txt"/></ws:attachment></ws:receive>
CitrusReferenceGuide
292Soap
![Page 293: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/293.jpg)
AgainweusetheCitrusSOAPextensionnamespacewiththespecificreceiveactionthatisawareofSOAPattachmentvalidation.Thetestercanvalidatethecontent-id,thecontent-typeandtheattachmentcontent.InsteadofusingtheexternalfileresourceyoucouldalsodefineanexpectedattachmenttemplatedirectlyinthetestcaseasinlineCDATAsection.
NoteThews:attachmentelementspecifiesavalidatorinstance.Thisvalidatordetermineshowtovalidatetheattachmentcontent.SOAPattachmentsarenotlimitedtoXMLcontent.Plaintextcontentandbinarycontentispossible,too.SoeachSOAPattachmentvalidatingactioncanuseadifferentSoapAttachmentValidatorinstancewhichisresponsibleforvalidatingandcomparingreceivedattachmentstoexpectedtemplateattachments.IntheCitrusconfigurationthevalidatorissetasnormalSpringbeanwiththerespectiveidentifier.
<beanid="soapAttachmentValidator"class="com.consol.citrus.ws.validation.SimpleSoapAttachmentValidator"<beanid="mySoapAttachmentValidator"class="com.company.ws.validation.MySoapAttachmentValidator"
YoucandefineseveralvalidatorinstancesintheCitrusconfiguration.Thevalidatorwiththegeneralid"soapAttachmentValidator"isthedefaultvalidatorforallactionsthatdonotexplicitlysetavalidatorinstance.Citrusoffersasetofreferencevalidatorimplementations.TheSimpleSoapAttachmentValidatorwilluseasimpleplaintextcomparison.Ofcourseyouareabletoaddindividualvalidatorimplementations,too.
SOAPMTOMsupport
MTOM(MessageTransmissionOptimizationMechanism)enablesyoutosendandreceivelargeSOAPmessagecontentusingstreameddatahandlers.Thisoptimizestheresourceallocationonserverandclientsidewherenotalldataisloadedintomemorywhenmarshalling/unmarshallingthemessagepayloaddata.IndetailMTOMenabledmessagesdohaveaXOPpackageinsidethemessagepayloadreplacingtheactuallargecontentdata.Thecontentisthenstreamedaasseparateattachment.Serverandclientcanoperatewithadatahandlerprovidingaccesstothestreamedcontent.ThisisveryhelpfulwhenusinglargebinarycontentinsideaSOAPmessageforinstance.
CitrusisabletobothsendandreceiveMTOMenabledSOAPmessagesonclientandserver.Justusethemtom-enabledflagwhensendingaSOAPmessage:
<ws:sendendpoint="soapMtomClient"mtom-enabled="true"><message>
CitrusReferenceGuide
293Soap
![Page 294: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/294.jpg)
<data><![CDATA[<image:addImagexmlns:image="http://www.citrusframework.org/imageService/"><image>cid:IMAGE</image></image:addImage>]]></data></message><ws:attachmentcontent-id="IMAGE"content-type="application/octet-stream"><ws:resourcefile="classpath:com/consol/citrus/hugeImageData.png"/></ws:attachment></ws:send>
AsyoucanseetheexampleabovesendsaSOAPmessagethatcontainsalargebinaryimagecontent.Theactualbinaryimagedataisreferencedwithacontentidmarkercid:IMAGEinsidethemessagepayload.Theactualimagecontentisaddedasattachmentwithaseparatefileresource.Importantisherethecontent-idwhichmatchestheidmarkerintheSOAPmessagepayload(IMAGE).
CitrusbuildsaproperSOAPMTOMenabledmessageautomaticallyaddingtheXOPpackageinsidethemessage.ThebinarydataissentasseparateSOAPattachmentaccordingly.TheresultingSOAPmessagelookslikethis:
<SOAP-ENV:Envelopexmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header></SOAP-ENV:Header><SOAP-ENV:Body><image:addImagexmlns:image="http://www.citrusframework.org/imageService/"><image><xop:Includexmlns:xop="http://www.w3.org/2004/08/xop/include"href="cid:IMAGE"/></image:addImage></SOAP-ENV:Body></SOAP-ENV:Envelope>
OntheserversideCitrusisalsoabletohandleMTOMenabledSOAPmessages.InaserverreceiveactionyoucanspecifytheMTOMSOAPattachmentcontentasfollows.
<ws:receiveendpoint="soapMtomServer"mtom-enabled="true"><messageschema-validation="false"><data><![CDATA[<image:addImagexmlns:image="http://www.citrusframework.org/imageService/"><image><xop:Includexmlns:xop="http://www.w3.org/2004/08/xop/include"href="cid:IMAGE"/></image></image:addImage>]]></data></message>
CitrusReferenceGuide
294Soap
![Page 295: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/295.jpg)
<ws:attachmentcontent-id="IMAGE"content-type="application/octet-stream"><ws:resourcefile="classpath:com/consol/citrus/hugeImageData.png"/></ws:attachment></ws:receive>
WedefinetheMTOMattachmentcontentasseparateSOAPattachment.Thecontent-idisreferencedsomewhereintheSOAPmessagepayloaddata.AtruntimeCitruswilladdtheXOPpackagedefinitionautomaticallyandperformvalidationonthemessageanditsstreamedMTOMattachmentdata.
NextthingthatwehavetotalkaboutisinlineMTOMdata.Thismeansthatthecontentshouldbeaddedaseitherbase64BinaryorhexBinaryencodedStringdatadirectlytothemessagecontent.Seethefollowingexamplethatusesthemtom-inlinesetting:
<ws:sendendpoint="soapMtomClient"mtom-enabled="true"><message><data><![CDATA[<image:addImagexmlns:image="http://www.citrusframework.org/imageService/"><image>cid:IMAGE</image><icon>cid:ICON</icon></image:addImage>]]></data></message><ws:attachmentcontent-id="IMAGE"content-type="application/octet-stream"mtom-inline="true"encoding-type="base64Binary"><ws:resourcefile="classpath:com/consol/citrus/image.png"/></ws:attachment><ws:attachmentcontent-id="ICON"content-type="application/octet-stream"mtom-inline="true"encoding-type="hexBinary"><ws:resourcefile="classpath:com/consol/citrus/icon.ico"/></ws:attachment></ws:send>
ThelistingabovedefinestwoinlineMTOMattachments.Thefirstattachmentcid:IMAGEusestheencodingtypebase64Binarywhichisthedefault.Thesecondattachmentcid:ICONuseshexBinaryencoding.Bothattachmentsareaddedasinlinedatabeforethemessageissent.ThefinalSOAPmessagelookslikefollows:
<SOAP-ENV:Envelopexmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header></SOAP-ENV:Header><SOAP-ENV:Body><image:addImagexmlns:image="http://www.citrusframework.org/imageService/"><image>VGhpcyBpcyBhIGJpbmFyeSBpbWFnZSBhdHRhY2htZW50IQpWYXJpYWJsZXMgJXt0ZXN0fSBzaG91bGQgbm90IGJlIHJlcGxhY2VkIQ==
CitrusReferenceGuide
295Soap
![Page 296: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/296.jpg)
<icon>5468697320697320612062696E6172792069636F6E206174746163686D656E74210A5661726961626C657320257B746573747D2073686F756C64206E6F74206265207265706C6163656421</image:addImage></SOAP-ENV:Body></SOAP-ENV:Envelope>
Theimagecontentisabase64BinaryStringandtheiconaheyBinaryString.OfcoursethismechanismalsoissupportedinreceiveactionsontheserversidewheretheexpectedmessagecontentisaddedalsinlineMTOMdatabeforevalidationtakesplace.
SOAPclientbasicauthentication
AsaSOAPclientyoumayhavetousebasicauthenticationinordertoaccessaserverresource.BasicauthenticationviaHTTPstandsforusername/passwordauthenticationwherethecredentialsaretransmittedintheHTTPrequestheadersectionasbase64encodedentry.AsCitrususestheSpringWebServicestackwecanusethebasicauthenticationsupportthere.WesettheusercredentialsontheHttpClientmessagesenderwhichisusedinsidetheSpringWebServiceTemplate.
CitrusprovidesacomfortablewaytosettheHTTPmessagesenderwithbasicauthenticationcredentialsontheWebServiceTemplate.Justseethefollowingexampleandlearnhowtodothat.
<citrus-ws:clientid="soapClient"request-url="http://localhost:8090/test"message-sender="basicAuthClient"/>
<beanid="basicAuthClient"class="org.springframework.ws.transport.http.HttpComponentsMessageSender"<propertyname="authScope"><beanclass="org.apache.http.auth.AuthScope"><constructor-argvalue="localhost"/><constructor-argvalue="8090"/><constructor-argvalue=""/><constructor-argvalue="basic"/></bean></property><propertyname="credentials"><beanclass="org.apache.http.auth.UsernamePasswordCredentials"><constructor-argvalue="someUsername"/><constructor-argvalue="somePassword"/></bean></property></bean>
CitrusReferenceGuide
296Soap
![Page 297: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/297.jpg)
TheaboveconfigurationresultsinSOAPrequestswithauthenticationheadersproperlysetforbasicauthentication.ThespecialmessagesendertakescareonaddingtheproperbasicauthenticationheadertoeachrequestthatissentwiththisCitrusmessagesender.Bydefaultpreemtiveauthenticationisused.Themessagesenderonlysendsasinglerequesttotheserverwithallauthenticationinformationsetinthemessageheader.Therequestwhichdeterminestheauthenticationschemeontheserverisskipped.ThisiswhyyouhavetoaddsomeauthscopesoCitruscansetupanauthenticationcachewithintheHTTPcontextinordertohavepreemtiveauthentication.
TipYoucanalsoskipthemessagesenderconfigurationandsettheAuthorizationheaderoneachrequestinyoursendactiondefinitiononyourown.BeawareofsettingtheheaderasHTTPmimeheaderusingthecorrectprefixandtakecareonusingthecorrectbasicauthenticationwithbase64encodingfortheusername:passwordphrase.
<header><elementname="citrus_http_Authorization"value="Basicc29tZVVzZXJuYW1lOnNvbWVQYXNzd29yZA=="</header>
Forbase64encodingyoucanalsouseaCitrusfunction,seefunctions-encode-base64
SOAPserverbasicauthentication
WhenprovidingSOAPWebServiceserverfunctionalityCitruscanalsosetbasicauthenticationsoallclientsneedtoauthenticateproperlywhenaccessingtheserverresource.
<citrus-ws:serverid="simpleSoapServer"port="8080"auto-start="true"resource-base="src/it/resources"security-handler="basicSecurityHandler"/>
<beanid="securityHandler"class="com.consol.citrus.ws.security.SecurityHandlerFactory"><propertyname="users"><list><beanclass="com.consol.citrus.ws.security.User"><propertyname="name"value="citrus"/><propertyname="password"value="secret"/><propertyname="roles"value="CitrusRole"/></bean></list></property><propertyname="constraints">
CitrusReferenceGuide
297Soap
![Page 298: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/298.jpg)
<map><entrykey="/foo/*"><beanclass="com.consol.citrus.ws.security.BasicAuthConstraint"><constructor-argvalue="CitrusRole"/></bean></entry></map></property></bean>
Wehavesetasecurityhandlerontheserverwebcontainerwithaconstraintonallresourceswith/foo/*.Followingfromthattheserverrequiresbasicauthenticationfortheseresources.Thegrantedusersandrolesarespecifiedwithinthesecurityhandlerbeandefinition.ConnectingclientshavetosetthebasicauthHTTPheaderproperlyusingthecorrectuserandroleforaccessingtheCitrusservernow.
Youcancustomizethesecurityhandlerforyourveryspecificneeds(e.g.loadusersandroleswithJDBCfromadatabase).Justhavealookatthecodebaseandinspectthesettingsandpropertiesofferedbythesecurityhandlerinterface.
TipThismechanismisnotrestrictedtobasicauthenticationonly.Withothersettingsyoucanalsosetupdigestorform-basedauthenticationconstraintsveryeasy.
WS-Addressingsupport
ThewebservicestackoffersalotofdifferenttechnologiesandstandardswithinthecontextofSOAPWebServices.WespeakofWS-*specificationsinparticular.Oneofthesespecificationsdealswithaddressing.OnclientsideyoumayaddwsaheaderinformationtotherequestinordertogivetheserverinstructionshowtodealwithSOAPfaultsforinstance.
InCitrusWebServiceclientyoucanaddthoseheaderinformationusingthecommonconfigurationlikethis:
<citrus-ws:clientid="soapClient"request-url="http://localhost:8090/test"message-converter="wsAddressingMessageConverter"/>
<beanid="wsAddressingMessageConverter"class="com.consol.citrus.ws.message.converter.WsAddressingMessageConverter"<constructor-arg><beanid="wsAddressing200408"class="com.consol.citrus.ws.addressing.WsAddressingHeaders"<propertyname="version"value="VERSION200408"/><propertyname="action"value="http://citrus.sample/sayHello"/><propertyname="to"value="http://citrus.sample/server"/>
CitrusReferenceGuide
298Soap
![Page 299: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/299.jpg)
<propertyname="from"><beanclass="org.springframework.ws.soap.addressing.core.EndpointReference"><constructor-argvalue="http://citrus.sample/client"/></bean></property><propertyname="replyTo"><beanclass="org.springframework.ws.soap.addressing.core.EndpointReference"><constructor-argvalue="http://citrus.sample/client"/></bean></property><propertyname="faultTo"><beanclass="org.springframework.ws.soap.addressing.core.EndpointReference"><constructor-argvalue="http://citrus.sample/fault/resolver"/></bean></property></bean></constructor-arg></bean>
TheWsAddressingheadervalueswillbeusedforallrequestmessagesthataresentwiththesoapclientcomponentsoapClient.YoucanoverwritetheWsAddressingheaderineachsendtestactioninyourtestthough.JustsetthespecialWsAddressingmessageheaderonyourrequest.Youcanusethefollowingmessageheadernamesinordertooverwritethedefaultaddressingheadersspecifiedinthemessageconverterconfiguration(alsoseetheclasscom.consol.citrus.ws.addressing.WsAddressingMessageHeaders).
citrus_soap_ws_addressing_messageIdaddressingmessageidasURIcitrus_soap_ws_addressing_fromaddressingfromendpointreferenceasURIcitrus_soap_ws_addressing_toaddressingtoURIcitrus_soap_ws_addressing_actionaddressingactionURIcitrus_soap_ws_addressing_replyToaddressingreplytoendpointreferenceasURIcitrus_soap_ws_addressing_faultToaddressingfaulttoendpointreferenceasURI
WhenusingthismessageheadersyouareabletoexplicitlyoverwritetheWsAddressingheaders.Testvariablesaresupportedofcoursewhenspecifyingthevalues.MostofthevaluesareparsedtoaURIvalueattheendsopleasemakesuretousecorrectURIStringrepresentations.
NoteTheWS-Addressingspecificationknowsseveralversions.Supportedversionare:
VERSION10(WS-Addressing1.0May2006)
CitrusReferenceGuide
299Soap
![Page 300: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/300.jpg)
VERSION200408(August2004editionoftheWS-Addressingspecification)
TheaddressingheadersfindaplaceintheSOAPmessageheaderwithrespectivenamespacesandvalues.ApossibleSOAPrequestwithWSaddressingheaderslookslikefollows:
<SOAP-ENV:Envelopexmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Headerxmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"><wsa:ToSOAP-ENV:mustUnderstand="1">http://citrus.sample/server</wsa:To><wsa:From><wsa:Address>http://citrus.sample/client</wsa:Address></wsa:From><wsa:ReplyTo><wsa:Address>http://citrus.sample/client</wsa:Address></wsa:ReplyTo><wsa:FaultTo><wsa:Address>http://citrus.sample/fault/resolver</wsa:Address></wsa:FaultTo><wsa:Action>http://citrus.sample/sayHello</wsa:Action><wsa:MessageID>urn:uuid:4c4d8af2-b402-4bc0-a2e3-ad33b910e394</wsa:MessageID></SOAP-ENV:Header><SOAP-ENV:Body><cit:HelloRequestxmlns:cit="http://citrus/sample/sayHello"><cit:Text>HelloCitrus!</cit:Text></cit:HelloRequest></SOAP-ENV:Body></SOAP-ENV:Envelope>
ImportantBydefaultwhennotsetexplicitlyonthemessageheaderstheWsAddressingmessageidpropertyisautomaticallygeneratedforeachrequest.YoucansetthemessageidgenerationstrategyintheSpringapplicationcontextmessageconverterconfiguration:
<beanid="wsAddressingMessageConverter"class="com.consol.citrus.ws.message.converter.WsAddressingMessageConverter"<propertyname="messageIdStrategy"><beanclass="org.springframework.ws.soap.addressing.messageid.UuidMessageIdStrategy"/></property></bean>
BydefaultthestrategywillcreateanewJavaUUIDforeachrequest.Thestrategyalsousesacommonresourcenameprefixurn:uuid:.Youcanoverwritethemessageidanytimeforeachrequestexplicitlybysettingthemessageheadercitrus_soap_ws_addressing_messageIdwitharespectivevalueonthemessageinyourtest.
CitrusReferenceGuide
300Soap
![Page 301: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/301.jpg)
SOAPclientforkmode
SOAPoverHTTPusessynchronouscommunicationbynature.ThismeansthatsendingaSOAPmessageinCitrusoverHTTPwillautomaticallyblockfurthertestactionsuntilthesynchronousHTTPresponsehasbeenreceived.Intestcasesthissynchronousblockingmightcauseproblemsforseveralreasons.AsimplereasonwouldbethatyouneedtodofurthertestactionsinparalleltothesynchronousHTTPSOAPcommunication(e.g.simulateanotherbackendsysteminthetestcase).
YoucanseparatetheSOAPsendactionfromtherestofthetestcasebyusingthe"fork"mode.TheSOAPclientwillautomaticallyopenanewJavaThreadforthesynchronouscommunicationandthetestisabletocontinuewithexecutionalthoughthesynchronousHTTPSOAPresponsehasnotarrivedyet.
<ws:sendendpoint="soapClient"fork="true"><message><payload><SoapRequestxmlns="http://www.consol.de/schemas/sample.xsd"><Operation>Readtheattachment</Operation></SoapRequest></payload></message></ws:send>
Withthe"fork"modeenabledthetestcontinueswithexecutionwhilethesendingactionwaitsforthesynchronousresponseinaseparateJavaThread.Youcouldreachthesamebehaviourwithacomplex/containerconstruct,butforkingthesendactionismuchmorestraightforward.
ImportantItishighlyrecommendedtouseaproper"timeout"settingontheSOAPreceiveactionwhenusingforkmode.Theforkedsendoperationmighttakesometimeandthecorrespondingreceiveactionmightrunintofailureastheresponsewashasnotbeenreceivedyet.Theresultwouldbeabrokentestbecauseofthemissingresponsemessage.Aproper"timeout"settingforthereceiveactionsolvesthisproblemastheactionwaitsforthistimeperiodandoccasionallyrepeatedlyasksfortheSOAPresponsemessage.Thefollowinglistingsetsthereceivetimeoutto10seconds,sotheactionwaitsfortheforkedsendactiontodelivertheSOAPresponseintime.
<ws:receiveendpoint="soapClient"timeout="10000"><message><payload><SoapResponsexmlns="http://www.consol.de/schemas/sample.xsd">
CitrusReferenceGuide
301Soap
![Page 302: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/302.jpg)
<Operation>Didsomething</Operation><Success>true</Success></SoapResponse></payload></message></ws:receive>
SOAPservletcontextcustomization
ForhighlycustomizedSOAPservercomponentsinCitrusyoucandefineafullservletcontextconfigurationfile.HereyouhavethefullpowertoaddSpringendpointmappingsandcustomendpointimplementations.Youcansetthecustomservletcontextasexternalfileresourceontheservercomponent:
<citrus-ws:clientid="soapClient"context-config-location="classpath:citrus-ws-servlet.xml"message-factory="soap11MessageFactory"/>
Nowletushaveacloserlookatthecontext-config-locationattribute.ThisconfigurationdefinestheSpringapplicationcontextfileforendpoints,requestmappingsandotherSpringWSspecificinformation.PleaseseetheofficialSpringWSdocumentationfordetailsonthisSpringbasedconfiguration.Youcanalsojustcopythefollowingexampleapplicationcontextwhichshouldworkforyouingeneral.
<beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd">
<beanid="loggingInterceptor"class="org.springframework.ws.server.endpoint.interceptor.PayloadLoggingInterceptor"><description>Thisinterceptorlogsthemessagepayload.</description></bean>
<beanid="helloServicePayloadMapping"class="org.springframework.ws.server.endpoint.mapping.PayloadRootQNameEndpointMapping"><propertyname="mappings"><props><propkey="http://www.consol.de/schemas/sayHelloHelloRequest">helloServiceEndpoint</prop>
CitrusReferenceGuide
302Soap
![Page 303: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/303.jpg)
</props></property><propertyname="interceptors"><list><refbean="loggingInterceptor"/></list></property></bean>
<beanid="helloServiceEndpoint"class="com.consol.citrus.ws.server.WebServiceEndpoint"><propertyname="endpointAdapter"ref="staticResponseEndpointAdapter"/></bean>
<citrus:static-response-adapterid="staticResponseEndpointAdapter"><citrus:payload><![CDATA[<HelloResponsexmlns="http://www.consol.de/schemas/sayHello"><MessageId>123456789</MessageId><CorrelationId>CORR123456789</CorrelationId><User>WebServer</User><Text>HelloUser</Text></HelloResponse>]]></citrus:payload><citrus:header><citrus:elementname="http://www.consol.de/schemas/samples/sayHello.xsdns0:Operation"value="sayHelloResponse"/><citrus:elementname="http://www.consol.de/schemas/samples/sayHello.xsdns0:Request"value="HelloRequest"/><citrus:elementname="citrus_soap_action"value="sayHello"/></citrus:header></citrus:static-response-adapter></beans>
TheprogramlistingabovedescribesanormalSpringWSrequestmappingwithendpointconfigurations.Themappingisresponsibletoforwardincomingrequeststotheendpointwhichwillhandletherequestandprovideaproperresponsemessage.Firstofallweaddalogginginterceptortothecontextsoallincomingrequestsgetloggedtotheconsolefirst.Thenweuseapayloadmapping(PayloadRootQNameEndpointMapping)inordertomapallincoming'HelloRequest'SOAPmessagestothe'helloServiceEndpoint'.EndpointsareofessentialnatureinCitrusSOAPWebServicesimplementation.Theyareresponsibleforprocessingarequestinordertoprovideaproperresponsemessagethatissentbacktothecallingclient.Citrususestheendpointincombinationwithamessageendpointadapterimplementation.
CitrusReferenceGuide
303Soap
![Page 304: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/304.jpg)
Theendpointworkstogetherwiththemessageendpointadapterthatisresponsibleforprovidingaresponsemessagefortheclient.ThevariousmessageendpointadapterimplementationsinCitruswerealreadydiscussedinendpoint-adapter.
Inthisexamplethe'helloServiceEndpoint'usesthe'static-response-adapter'whichisalwaysreturningastaticresponsemessage.Inmostcasesstaticresponseswillnotfitthetestscenarioandyouwillhavetorespondmoredynamically.
RegardlessofwhichmessageendpointadaptersetupyouareusinginyourtestcasetheendpointtransformstheresponseintoaproperSOAPmessage.Youcanaddasmanyrequestmappingsandendpointsasyouwanttotheservercontextconfiguration.SoyouareabletohandledifferentrequesttypeswithonesingleJettyserverinstance.
That'sitforconnectingwithSOAPWebServices!WesawhowtosendandreceiveSOAPmessageswithJettyandSpringWebServices.HavealookatthesamplescomingwithyourCitrusarchiveinordertolearnmoreabouttheSOAPmessagehandling.
CitrusReferenceGuide
304Soap
![Page 305: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/305.jpg)
FTPsupportCitrusisabletostartalittleftpserveracceptingincomingclientrequests.AlsoCitrusisabletocallFTPcommandsasaclient.ThenextsectionsdealwithFTPconnectivity.
NoteTheFTPcomponentsinCitrusarekeptinaseparateMavenmodule.SoyoushouldaddthemoduleasMavendependencytoyourprojectaccordingly.
<dependency><groupId>com.consol.citrus</groupId><artifactId>citrus-ftp</artifactId><version>2.7.1</version></dependency>
AsCitrusprovidesacustomizedFTPconfigurationschemafortheSpringapplicationcontextconfigurationfileswehavetoaddnametothetoplevelbeanselement.Simplyincludetheftp-confignamespaceintheconfigurationXMLfilesasfollows.
<beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:citrus="http://www.citrusframework.org/schema/config"xmlns:citrus-ftp="http://www.citrusframework.org/schema/ftp/config"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.citrusframework.org/schema/confighttp://www.citrusframework.org/schema/config/citrus-config.xsdhttp://www.citrusframework.org/schema/http/confighttp://www.citrusframework.org/schema/ftp/config/citrus-ftp-config.xsd">
[...]
</beans>
NowwearereadytousethecustomizedCitrusFTPconfigurationelementswiththecitrus-ftpnamespaceprefix.
FTPclient
CitrusReferenceGuide
305Ftp
![Page 306: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/306.jpg)
WewanttouseCitrusfoconnecttodomeFTPserverasaclientsendingcommandssuchascreatingadirectoryorlistingallfiles.CitrusoffersaclientcomponentdoingexactlythisFTPclientconnection.
<citrus-ftp:clientid="ftpClient"host="localhost"port="22222"username="admin"password="admin"timeout="10000"/>
TheconfigurationabovedescribesaCitrusftpclientconnectedtoaftpserverwithftp://localhost:22222.Forauthenticationusernameandpasswordaredefinedaswellastheglobalconnectiontimeout.Theclientwillautomaticallysendusernameandpasswordforproperauthenticationtotheserverwhenopeninganewconnection.
Inatestcaseyouarenowabletousetheclienttopushcommandstotheserver.
<sendendpoint="ftpClient"fork="true"><message><data></data></message><header><elementname="citrus_ftp_command"value="PWD"/><elementname="citrus_ftp_arguments"value="test"/></header></send>
<receiveendpoint="ftpClient"><messagetype="plaintext"><data>PWD</data></message><header><elementname="citrus_ftp_command"value="PWD"/><elementname="citrus_ftp_arguments"value="test"/><elementname="citrus_ftp_reply_code"value="257"/><elementname="citrus_ftp_reply_string"value="@contains('iscurrentdirectory')@"/></header></receive>
Asyoucanseemostoftheftpcommunicationparametersarespecifiedasspecialheaderelementsinthemessage.CitrusautomaticallyconvertsthoseinformationtoproperFTPcommandsandresponsemessages.
FTPserver
CitrusReferenceGuide
306Ftp
![Page 307: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/307.jpg)
NowthatweareabletoaccessFTPasaclientwemightalsowanttosimulatetheserverside.ThereforeCitrusoffersaservercomponentthatislisteningonaportforincomingFTPconnections.Theserverhasadefaulthomedirectoryonthelocalfilesystemspecified.Butyoucanalsodefinehomedirectoriesperuser.Fornowletushavealookattheserverconfigurationcomponent:
<citrus-ftp:serverid="ftpServer">port="22222"auto-start="true"user-manager-properties="classpath:ftp.server.properties"/>
Theftpserverconfigurationisquitesimple.Theserverstartsautomaticallyandbindstoaport.Theuserconfigurationisreadfromauser-manager-propertyfile.Letushavealookatthecontentofthisusermanagementfile:
#Passwordis"admin"ftpserver.user.admin.userpassword=21232F297A57A5A743894A0E4A801FC3ftpserver.user.admin.homedirectory=target/ftp/user/adminftpserver.user.admin.enableflag=trueftpserver.user.admin.writepermission=trueftpserver.user.admin.maxloginnumber=0ftpserver.user.admin.maxloginperip=0ftpserver.user.admin.idletime=0ftpserver.user.admin.uploadrate=0ftpserver.user.admin.downloadrate=0
ftpserver.user.anonymous.userpassword=ftpserver.user.anonymous.homedirectory=target/ftp/user/anonymousftpserver.user.anonymous.enableflag=trueftpserver.user.anonymous.writepermission=falseftpserver.user.anonymous.maxloginnumber=20ftpserver.user.anonymous.maxloginperip=2ftpserver.user.anonymous.idletime=300ftpserver.user.anonymous.uploadrate=4800ftpserver.user.anonymous.downloadrate=4800
Asyoucanseeyouareabletodefineasmanyuserfortheftpserverasyoulike.Usernameandpassworddefinetheauthenticationontheserver.Inadditiontothatyouhaveplentyofconfigurationpossibilitiesperuser.CitrususestheApacheftpserverimplementation.SoformoredetailsonconfigurationcapabilitiespleaseconsulttheofficialApacheftpserverdocumentation.
CitrusReferenceGuide
307Ftp
![Page 308: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/308.jpg)
Nowwewouldliketousetheserverinatestcase.Veryeasyyoujusthavetodefineareceivemessageactionwithinyourtestcasethatusestheserveridasendpointreference:
<echo><message>ReceiveuserloginonFTPserver</message></echo>
<receiveendpoint="ftpServer"><messagetype="plaintext"><data>USER</data></message><header><elementname="citrus_ftp_command"value="USER"/><elementname="citrus_ftp_arguments"value="admin"/></header></receive>
<sendendpoint="ftpServer"><messagetype="plaintext"><data>OK</data></message></send>
<echo><message>ReceiveuserpasswordonFTPserver</message></echo>
<receiveendpoint="ftpServer"><messagetype="plaintext"><data>PASS</data></message><header><elementname="citrus_ftp_command"value="PASS"/><elementname="citrus_ftp_arguments"value="admin"/></header></receive>
<sendendpoint="ftpServer"><messagetype="plaintext""><data>OK</data></message></send>
Thelistingaboveshowstwoincomingcommandsrepresentingauserlogin.Weindicatewithresendactionsthatwewouldlinktheservertorespondwithpositivefeedbackandtoacceptthelogin.Aswehaveafullyqualifiedftpserverrunningtheclientcanalso
CitrusReferenceGuide
308Ftp
![Page 309: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/309.jpg)
pushfilesreaddirectoriesandmore.Allincomingcommandscanbevalidatedinsideatestcase.
CitrusReferenceGuide
309Ftp
![Page 310: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/310.jpg)
MessagechannelsupportMessagechannelsrepresenttheinmemorymessagingsolutioninCitrus.Producerandconsumercomponentsarelinkedviachannelsexchangingmessagesinmemory.AsthistransportmechanismcomesfromSpringIntegrationAPI(http://www.springsource.org/spring-integration)andCitrusitselfusesalotofSpringAPIs,especiallythosefromSpringIntegrationyouareabletoconnecttoallSpringmessagingadaptersviatheseinmemorychannels.
CitrusoffersachannelcomponentsthatcanbeusedbothbyCitrusandSpringIntegration.TheconclusionisthatCitrussupportsthesendingandreceivingofmessagesbothtoandfromSpringIntegrationmessagechannelcomponents.ThisopensupalotofgreatpossibilitiestointeractwiththeSpringIntegrationtransportadaptersforFTP,TCP/IPandsoon.Inadditiontothatthemessagechannelsupportprovidesusagoodwaytoexchangemessagesinmemory.
CitrusprovidessupportforsendingandreceivingJMSmessages.Wehavetoseparatebetweensynchronousandasynchronouscommunication.SointhischapterweexplainhowtosetupJMSmessageendpointsforsynchronousandasynchronousoutboundandinboundcommunication
NoteThemessagechannelconfigurationcomponentsusethedefault"citrus"configurationnamespaceandschemadefinition.IncludethisnamespaceintoyourSpringconfigurationinordertousetheCitrusconfigurationelements.ThenamespaceURIandschemalocationareaddedtotheSpringconfigurationXMLfileasfollows.
<beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:citrus-jms="http://www.citrusframework.org/schema/config"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.citrusframework.org/schema/confighttp://www.citrusframework.org/schema/config/citrus-config.xsd">
[...]
</beans>
AfterthatyouareabletousecustomizedCitrusXMLelementsinordertodefinetheSpringbeans.
CitrusReferenceGuide
310Messagechannel
![Page 311: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/311.jpg)
Channelendpoint
Citrusoffersachannelendpointcomponentthatisabletocreateproducerandconsumercomponents.Producerandconsumersendandreceivemessagesbothtoandfromachannelendpoint.BydefaulttheendpointisasynchronouswhenconfiguredintheCitrusapplicationcontext.Withthiscomponentyouareabletoaccessmessagechannelsdirectly:
<citrus:channel-endpointid="helloEndpoint"channel="helloChannel"/>
<si:channelid="helloChannel"/>
TheCitruschannelendpointreferencesaSpringIntegrationchanneldirectly.InsideyourtestcaseyoucanreferencetheCitrusendpointasusualtosendandreceivemessages.Wewillseethislaterinsomeexamplecodelistings.
NoteTheSpringIntegrationconfigurationcomponentsuseaspecificnamespacethathastobeincludedintoyourSpringapplicationcontext.Youcanusethefollowingtemplatewhichholdsallnecessarynamespacesandschemalocations:
<?xmlversion="1.0"encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:citrus="http://www.citrusframework.org/schema/config"xmlns:si="http://www.springframework.org/schema/integration"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.citrusframework.org/schema/confighttp://www.citrusframework.org/schema/config/citrus-config.xsdhttp://www.springframework.org/schema/integrationhttp://www.springframework.org/schema/integration/spring-integration.xsd"></beans>
TheCitruschannelendpointalsosupportsacustomizedmessagechanneltemplatethatwillactuallysendthemessages.Thecustomizedtemplatemightgiveyouaccesstospecialconfigurationpossibilities.Howeveritisoptional,soifnomessagechanneltemplateisdefinedintheconfigurationCitruswillcreateadefaulttemplate.
<citrus:channel-endpointid="helloEndpoint"channel="helloChannel"message-channel-template="myMessageChannelTemplate"/>
CitrusReferenceGuide
311Messagechannel
![Page 312: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/312.jpg)
Themessagesenderisnowreadytopublishmessagestothedefinedchannel.Thecommunicationissupposedtobeasynchronous,sotheproducerisnotabletoprocessareplymessage.Wewilldealwithsynchronouscommunicationandreplymessageslaterinthischapter.Themessageproducerjustpublishesmessagestothechannelandisdone.Interactingwiththeendpointsinatestcaseisquiteeasy.Justreferencetheidoftheendpointinyoursendandreceivetestactions
<sendendpoint="helloEndpoint"><message><payload><v1:HelloRequestxmlns:v1="http://citrusframework.org/schemas/HelloService.xsd"><v1:Text>HelloWorld!</v1:Text></v1:HelloRequest></payload></message></send>
<receiveendpoint="helloEndpoint"><message><payload><v1:HelloResponsexmlns:v1="http://citrusframework.org/schemas/HelloService.xsd"><v1:Text>HelloCitrus!</v1:Text></v1:HelloResponse></payload></message></receive>
AsyoucanseeCitrusisalsoabletoreceivemessagesfromthesameSpringIntegrationmessagechanneldestination.Wejustreferencesthesamechannel-endpointinthereceiveaction.
Asusualthereceiverconnectstothemessagedestinationandwaitsformessagestoarrive.Theusercansetareceivetimeoutwhichissetto5000millisecondsbydefault.Incasenomessagewasreceivedinthistimeframethereceiverraisestimeouterrorsandthetestfails.
Synchronouschannelendpoints
Thesynchronouschannelproducerpublishesmessagesandwaitssynchronouslyfortheresponsetoarriveonsomereplychanneldestination.Thereplychannelnameissetinthemessage'sheaderattributessothecounterpartinthiscommunicationcansendits
CitrusReferenceGuide
312Messagechannel
![Page 313: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/313.jpg)
replytothatchannel.Thebasicconfigurationforasynchronouschannelendpointcomponentlookslikefollows:
<citrus:channel-sync-endpointid="helloSyncEndpoint"channel="helloChannel"reply-timeout="1000"polling-interval="1000"/>
Synchronousmessagechannelendpointsusuallydopollforsynchronousreplymessagesforprocessingthereplymessages.Thepollintervalisanoptionalsettinginordertomanagetheamountofreplymessagehandshakeattempts.Oncetheendpointwasabletoreceivethereplymessagesynchronouslythetestcasecanreceivethereply.Incaseallmessagehandshakeattemptsdofailbecausethereplymessageisnotavailableintimeweraisesometimeouterrorandthetestwillfail.
NoteBydefaultthechannelendpointusestemporaryreplychanneldestinations.Thetemporaryreplychannelsareonlyusedonceforasinglecommunicationhandshake.Afterthatthereplychannelisdeletedagain.Staticreplychannelsarenotsupportedasithasnotbeeninscopeyet.
Whensendingamessagetothisendpointinthefirstplacetheproducerwillwaitsynchronouslyfortheresponsemessagetoarriveonthereplydestination.Youcanreceivethereplymessageinyourtestcaseusingthesameendpointcomponent.Sowehavetwoactionsonthesameendpoint,firstsendthenreceive.
<sendendpoint="helloSyncEndpoint"><message><payload><v1:HelloRequestxmlns:v1="http://citrusframework.org/schemas/HelloService.xsd"><v1:Text>HelloWorld!</v1:Text></v1:HelloRequest></payload></message></send>
<receiveendpoint="helloSyncEndpoint"><message><payload><v1:HelloResponsexmlns:v1="http://citrusframework.org/schemas/HelloService.xsd"><v1:Text>HelloCitrus!</v1:Text></v1:HelloResponse></payload></message></receive>
CitrusReferenceGuide
313Messagechannel
![Page 314: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/314.jpg)
Inthelastsectionwesawthatsynchronouscommunicationisbasedonreplymessagesontemporaryreplychannels.WesawthatCitrusisabletopublishmessagestochannelsandwaitforreplymessagestoarriveontemporaryreplychannels.Thissectiondealswiththesamesynchronouscommunicationoverreplymessages,butnowCitrushastosenddynamicreplymessagestotemporarychannels.
ThescenariowearetalkingaboutisthatCitrusreceivesamessageandweneedtoreplytoatemporaryreplychannelthatisstoredinthemessageheaderattributes.Wehandlethissynchronouscommunicationwiththesamesynchronouschannelendpointcomponent.Wheninitiatingthecommunicationbyreceivingamessagefromasynchronouschannelendpointyouareabletosendasynchronousresponseback.Againjustusethesameendpointreferenceinyourtestcase.Thehandlingoftemporaryreplydestinationsisdoneautomaticallybehindthescenes.Sowehaveagaintwoactionsinourtestcase,butthistimefirstreceivethensend.
<receiveendpoint="helloSyncEndpoint"><message><payload><v1:HelloRequestxmlns:v1="http://citrusframework.org/schemas/HelloService.xsd"><v1:Text>HelloWorld!</v1:Text></v1:HelloRequest></payload></message></receive>
<sendendpoint="helloSyncEndpoint"><message><payload><v1:HelloResponsexmlns:v1="http://citrusframework.org/schemas/HelloService.xsd"><v1:Text>HelloCitrus!</v1:Text></v1:HelloResponse></payload></message></send>
Thesynchronousmessagechannelendpointwillhandleallreplychanneldestinationsandprovidethosebehindthescenes.
Messageselectorsonchannels
CitrusReferenceGuide
314Messagechannel
![Page 315: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/315.jpg)
UnfortunatelySpringIntegrationmessagechannelsdonotsupportmessageselectorsonheadervaluesasdescribedinmessage-selector.WithCitrusversion1.2wefoundawaytoalsoaddmessageselectorsupportonmessagechannels.Wehadtointroduceaspecialqueuemessagechannelimplementation.Sofirstofallweusethisnewmessagechannelimplementationinourconfiguration.
<citrus:channelid="orderChannel"capacity="5"/>
TheCitrusmessagechannelimplementationextendsthequeuechannelimplementationfromSpringIntegration.Sowecanaddacapacityattributeforthischannel.That'sit!Nowweusethemessagechannelthatsupportsmessageselection.Inourtestwedefinemessageselectorsonheadervaluesasdescribedinmessage-selectorandyouwillseethatitworks.
Inadditiontothatwehaveimplementedothermessagefilterpossibilitiesonmessagechannelsthatwediscussinthenextsections.
RootQNameMessageSelector
YoucanusetheXMLrootQNameofyourmessageasselectioncriteria.Let'sseehowthisworksinasmallexample:
WehavetwodifferentXMLmessagesonamessagechannelwaitingtobepickedupbyaconsumer.
<HelloMessagexmlns="http://citrusframework.org/schema">HelloCitrus</HelloMessage><GoodbyeMessagexmlns="http://citrusframework.org/schema">GoodbyeCitrus</GoodbyeMessage>
WewouldliketopickuptheGoodbyeMessageinourtestcase.TheHelloMessageshouldbeleftonthemessagechannelaswearenotinterestedinitrightnow.Wecandefinearootqnamemessageselectorinthereceiveactionlikethis:
<receiveendpoint="orderChannelEndpoint"><selector><elementname="root-qname"value="GoodbyeMessage"/></selector><message><payload><GoodbyeMessagexmlns="http://citrusframework.org/schema">GoodbyeCitrus</GoodbyeMessage</payload></message></receive>
CitrusReferenceGuide
315Messagechannel
![Page 316: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/316.jpg)
TheCitrusreceiverpicksuptheGoodbyeMessagefromthechannelselectedviatherootqnameoftheXMLmessagepayload.OfcourseyoucanalsocombinemessageheaderselectorsandrootqnameselectorsasshowninthisexamplebelowwhereamessageheadersequenceIdisaddedtotheselectionlogic.
<selector><elementname="root-qname"value="GoodbyeMessage"/><elementname="sequenceId"value="1234"/></selector>
AswedealwithXMLqnamevalues,wecanalsousenamespacesinourselectorrootqnameselection.
<selector><elementname="root-qname"value="http://citrusframework.org/schemaGoodbyeMessage"/></selector>
XPathEvaluatingMessageSelector
ItisalsopossibletoevaluatesomeXPathexpressiononthemessagepayloadinordertoselectamessagefromamessagechannel.TheXPathexpressionoutcomemustmatchanexpectedvalueandonlythenthemessageisconsumedformthechannel.
ThesyntaxfortheXPathexpressionistobedefinedastheelementnamelikethis:
<selector><elementname="xpath://Order/status"value="pending"/></selector>
Themessageselectorlooksforordermessageswithstatus="pending"inthemessagepayload.Thismeansthatfollowingmessageswouldgetaccepted/declinedbythemessageselector.
<Order><status>pending</status></Order>=ACCEPTED<Order><status>finished</status></Order>=NOTACCEPTED
OfcourseyoucanalsouseXMLnamespacesinyourXPathexpressionswhenselectingmessagesfromchannels.
CitrusReferenceGuide
316Messagechannel
![Page 317: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/317.jpg)
<selector><elementname="xpath://ns1:Order/ns1:status"value="pending"/></selector>
Namespaceprefixesmustmatchtheincomingmessage-otherwisetheXPathexpressionwillnotworkasexpected.Inourexamplethemessageshouldlooklikethis:
<ns1:Orderxmlns:ns1="http://citrus.org/schema"><ns1:status>pending</ns1:status></ns1:Order>
KnowingthecorrectXMLnamespaceprefixisnotalwayseasy.IfyouarenotsurewhichnamespaceprefixtochooseCitrusshipswithadynamicnamespacereplacementforXPathexpressions.TheXPathexpressionlookslikethisandismostflexible:
<selector><elementname="xpath://http://citrus.org/schema:Order/http://citrus.org/schema:status"value="pending"/></selector>
ThiswillmatchallincomingmessagesregardlesstheXMLnamespaceprefixthatisused.
CitrusReferenceGuide
317Messagechannel
![Page 318: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/318.jpg)
FilesupportInchaptermessage-channelwediscussedthenativeSpringIntegrationchannelsupportwhichenablesCitrustointeractwithallSpringIntegrationmessagingadapterimplementations.ThisisafantasticwaytoextendCitrusforadditionaltransports.ThisinteractionnowcomeshandywhenwritingandreadingfilesfromthefilesysteminCitrus.
Writefiles
WewanttousetheSpringIntegrationfileadapterforbothreadingandwritingfileswithalocaldirectory.Citruscaneasilyconnecttothisfileadapterimplementationwithitsmessagechannelsupport.CitrusmessagesenderandreceiverspeaktomessagechannelsthatareconnectedtotheSpringIntegrationfileadapters.
<citrus:channel-endpointid="fileEndpoint"channel="fileChannel"/>
<file:outbound-channel-adapterid="fileOutboundAdapter"channel="fileChannel"directory="file:$some.directory.property"/>
<si:channelid="fileChannel"/>
TheconfigurationabovedescribesaCitrusmessagechannelendpointconnectedtoaSpringIntegrationoutboundfileadapterthatwritesmessagestoastoragedirectory.WiththiscombinationyouareabletowritefilestoadirectoryinyourCitrustestcase.ThetestcaseusesthechannelendpointinitssendactionandtheendpointinteractswiththeSpringIntegrationfileadaptersosendingoutthefile.
NoteTheSpringIntegrationfileadapterconfigurationcomponentsaddanewnamespacetoourSpringapplicationcontext.Seethistemplatewhichholdsallnecessarynamespacesandschemalocations:
<?xmlversion="1.0"encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:citrus="http://www.citrusframework.org/schema/config"xmlns:si="http://www.springframework.org/schema/integration"xmlns:file="http://www.springframework.org/schema/integration/file"xsi:schemaLocation="http://www.springframework.org/schema/beans
CitrusReferenceGuide
318File
![Page 319: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/319.jpg)
http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.citrusframework.org/schema/confighttp://www.citrusframework.org/schema/config/citrus-config.xsdhttp://www.springframework.org/schema/integrationhttp://www.springframework.org/schema/integration/spring-integration.xsdhttp://www.springframework.org/schema/integration/filehttp://www.springframework.org/schema/integration/file/spring-integration-file.xsd"></beans>
Readfiles
Thenextprogramlistingshowsapossibleinboundfilecommunication.SotheSpringIntegrationfileinboundadapterwillreadfilesfromastoragedirectoryandpublishthefilecontentstoamessagechannel.Citruscanthenreceivethosefilesasmessagesinatestcaseviathechannelendpointandvalidatethefilecontentsforinstance.
<file:inbound-channel-adapterid="fileInboundAdapter"channel="fileChannel"directory="file:$some.directory.property"><si:pollerfixed-rate="100"/></file:inbound-channel-adapter>
<si:channelid="fileChannel"><si:queuecapacity="25"/><si:interceptors><beanclass="org.springframework.integration.transformer.MessageTransformingChannelInterceptor"<constructor-arg><beanclass="org.springframework.integration.file.transformer.FileToStringTransformer"</constructor-arg></bean></si:interceptors></si:channel>
<citrus:channel-endpointid="fileEndpoint"channel="fileChannel"/>
ImportantThefileinboundadapterconstructsJavafileobjectsasthemessagepayloadbydefault.CitruscanonlyworkonStringmessagepayloads.SoweneedafiletransformerthatconvertsthefileobjectstoStringpayloadsrepresentingthefile'scontent.
ThisfileadapterexampleshowshoweasyCitruscanworkhandinhandwithSpringIntegrationadapterimplementations.ThemessagechannelsupportisafantasticwaytoextendthetransportandprotocolsupportinCitrusbyconnectingwiththeverygood
CitrusReferenceGuide
319File
![Page 320: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/320.jpg)
SpringIntegrationadapterimplementations.HaveacloserlookattheSpringIntegrationprojectformoredetailsandotheradapterimplementationsthatyoucanusewithCitrusintegrationtesting.
CitrusReferenceGuide
320File
![Page 321: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/321.jpg)
ApacheCamelsupportApacheCamelprojectimplementstheenterpriseintegrationpatternsforbuildingmediationandroutingrulesinyourenterpriseapplication.WiththeCitrusCamelsupportyouareabletodirectlyinteractwiththeApacheCamelcomponentsandroutedefinitions.YoucancallCamelroutesandreceivesynchronousresponsemessages.YoucanalsosimulatetheCamelrouteendpointwithreceivingmessagesandprovidingsimulatedresponsemessages.
NoteThecamelcomponentsinCitrusarekeptinaseparateMavenmodule.SoyoushouldaddthemoduleasMavendependencytoyourprojectaccordingly.
<dependency><groupId>com.consol.citrus</groupId><artifactId>citrus-camel</artifactId><version>2.7.1</version></dependency>
CitrusprovidesaspecialApacheCamelconfigurationschemathatisusedinourSpringconfigurationfiles.Youhavetoincludethecitrus-camelnamespaceinyourSpringconfigurationXMLfilesasfollows.
<beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:citrus="http://www.citrusframework.org/schema/config"xmlns:citrus-camel="http://www.citrusframework.org/schema/camel/config"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.citrusframework.org/schema/confighttp://www.citrusframework.org/schema/config/citrus-config.xsdhttp://www.citrusframework.org/schema/camel/confighttp://www.citrusframework.org/schema/camel/config/citrus-camel-config.xsd">
[...]
</beans>
NowyouarereadytousetheCitrusApacheCamelconfigurationelementsusingthecitrus-camelnamespaceprefix.
ThenextsectionsexplaintheCitruscapabilitieswhileworkingwithApacheCamel.
CitrusReferenceGuide
321Camel
![Page 322: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/322.jpg)
Camelendpoint
CamelandCitrusbothusetheendpointpatterninordertodefinemessagedestinations.Userscaninteractwiththeseendpointswhencreatingthemediationandroutinglogic.TheCitrusendpointcomponentforCamelinteractionisdefinedasfollowsinyourCitrusSpringconfiguration.
<citrus-camel:endpointid="directCamelEndpoint"endpoint-uri="direct:news"/>
RightnexttothatCitrusendpointweneedtheApacheCamelroutethatislocatedinsideacamelcontextcomponent.
<camelContextid="camelContext"xmlns="http://camel.apache.org/schema/spring"><routeid="newsRoute"><fromuri="direct:news"/><touri="log:com.consol.citrus.camel?level=INFO"/><touri="seda:news-feed"/></route></camelContext>
AsyoucanseetheCitruscamelendpointisabletointeractwiththeCamelroute.IntheexampleabovetheCamelcontextisplacedasSpringbeanCamelcontext.ThiswouldbetheeasiestsetuptouseCamelwithCitrusasyoucanaddtheCamelcontextstraighttotheSpringbeanapplicationcontext.OfcourseyoucanalsoimportyourCamelcontextandroutesfromotherSpringbeancontextfilesoryoucanstarttheCamelcontextrouteswithJavacode.
IntheexampletheApacheCamelrouteislisteningontherouteendpointuridirect:news.IncomingmessageswillbeloggedtotheconsoleusingalogCamelcomponent.AfterthatthemessageisforwardedtoasedaCamelcomponentwhichisasimplequeueinmemory.SowehaveasmallCamelroutinglogicwithtwodifferentmessagetransports.
TheCitrusendpointcaninteractwiththissampleroutedefinition.TheendpointconfigurationholdstheendpointuriinformationthattellsCitrushowtoaccesstheApacheCamelroutedestination.ThisendpointuricanbeanyCamelendpointurithatisusedinaCamelroute.Herewejustusethedirectendpointuridirect:newssothesampleCamelroutegetscalleddirectly.Inyourtestcaseyoucanusethisendpoint
CitrusReferenceGuide
322Camel
![Page 323: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/323.jpg)
componentreferencedbyitsidornameinordertosendandreceivemessagesontherouteaddressdirect:news.TheCamelroutelisteningonthisdirectaddresswillbeinvokedaccordingly.
TheApacheCamelroutessupportasynchronousandsynchronousmessagecommunicationpatterns.BydefaultCitrususesasynchronouscommunicationwithCamelroutes.ThismeansthattheCitrusproducersendstheexchangemessagetotherouteendpointuriandisfinishedimmediately.Thereisnosynchronousresponsetoawait.IncontrarytothatthesynchronousendpointwillsendandreceiveasynchronousmessageontheCameldestinationroute.Wewilldiscussthislateroninthischapter.FornowwehavealookonhowtousetheCitruscamelendpointinatestcaseinordertosendamessagetotheCamelroute:
<sendendpoint="directCamelEndpoint"><messagetype="plaintext"><payload>HellofromCitrus!</payload></message></send>
TheCitruscamelendpointcomponentcanalsobeusedinareceivemessageactioninyourtestcase.Inthissituationyouwouldreceiveamessagefromtherouteendpoint.ThisisespeciallydesignedforqueueingendpointroutessuchastheCamelsedacomponent.InourexampleCamelrouteabovethesedaCamelcomponentiscalledwiththeendpointuriseda:news-feed.ThismeansthattheCamelrouteissendingamessagetothesedacomponent.Citrusisabletoreceivethisroutemessagewithaendpointcomponentlikethis:
<citrus-camel:endpointid="sedaCamelEndpoint"endpoint-uri="seda:news-feed"/>
YoucanusetheCitruscamelendpointinyourtestcasereceiveactioninordertoconsumethemessageonthesedacomponent.
<receiveendpoint="sedaCamelEndpoint"><messagetype="plaintext"><payload>HellofromCitrus!</payload></message></receive>
CitrusReferenceGuide
323Camel
![Page 324: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/324.jpg)
TipInsteadofdefiningastaticCitruscamelcomponentyoucouldalsousethedynamicendpointcomponentsinCitrus.Thiswouldenableyoutosendyourmessagedirectlyusingtheendpointuridirect:newsinyourtestcase.Readmoreaboutthisinendpoint-components.
CitrusisabletosendandreceivemessageswithCamelrouteendpointuri.ThisenablesyoutoinvokeaCamelroute.TheCamelcomponentsusedisdefinedbytheendpointuriasusual.WheninteractingwithCamelroutesyoumightneedtosendbacksomeresponsemessagesinordertosimulateboundaryapplications.Wewilldiscussthesynchronouscommunicationinthenextsection.
SynchronousCamelendpoint
ThesynchronousApacheCamelproducersendsamessagetosomerouteandwaitssynchronouslyfortheresponsetoarrive.InCamelthiscommunicationisrepresentedwiththeexchangepatternInOut.ThebasicconfigurationforasynchronousApacheCamelendpointcomponentlookslikefollows:
<citrus-camel:sync-endpointid="camelSyncEndpoint"endpoint-uri="direct:hello"timeout="1000"polling-interval="300"/>
Synchronousendpointspollforsynchronousreplymessagestoarrive.Thepollintervalisanoptionalsettinginordertomanagetheamountofreplymessagehandshakeattempts.Oncetheendpointwasabletoreceivethereplymessagesynchronouslythetestcasecanreceivethereply.Incasethereplymessageisnotavailableintimeweraisesometimeouterrorandthetestwillfail.
Inafirsttestscenariowewriteatestcasethesendsamessagetothesynchronousendpointandwaitsforthesynchronousreplymessagetoarrive.SowehavetwoactionsonthesameCitrusendpoint,firstsendthenreceive.
<sendendpoint="camelSyncEndpoint"><messagetype="plaintext"><payload>HellofromCitrus!</payload></message></send>
<receiveendpoint="camelSyncEndpoint"><messagetype="plaintext"><payload>ThisisthereplyfromApacheCamel!</payload>
CitrusReferenceGuide
324Camel
![Page 325: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/325.jpg)
</message></receive>
Thenextvariationdealswiththesamesynchronouscommunication,butsendandreceiverolesareswitched.NowCitrusreceivesamessagefromaCamelrouteandhastoprovideareplymessage.WehandlethissynchronouscommunicationwiththesamesynchronousApacheCamelendpointcomponent.Onlydifferenceisthatweinitiallystartthecommunicationbyreceivingamessagefromtheendpoint.KnowingthisCitrusisabletosendasynchronousresponseback.Againjustusethesameendpointreferenceinyourtestcase.Sowehaveagaintwoactionsinourtestcase,butthistimefirstreceivethensend.
<receiveendpoint="camelSyncEndpoint"><messagetype="plaintext"><payload>HellofromApacheCamel!</payload></message></receive>
<sendendpoint="camelSyncEndpoint"><messagetype="plaintext"><payload>ThisisthereplyfromCitrus!</payload></message></send>
Thisisprettysimple.CitrustakescareonsettingtheApacheCamelexchangepatternInOutwhileusingsynchronouscommunications.TheCamelroutesdorespondandCitrusisabletoreceivethesynchronousmessagesaccordingly.WiththispatternyoucaninteractwithApacheCamelrouteswhereCitrussimulatessynchronousclientsandconsumers.
Camelexchangeheaders
ApacheCamelusesexchangeswhensendingandreceivingmessagestoandfromroutes.Theseexchangesholdspecificinformationonthecommunicationoutcome.Citrusautomaticallyconvertstheseexchangeinformationtospecialmessageheaderentries.Youcanvalidatethoseexchangeheaderstheneasilyinyourtestcase:
<receiveendpoint="sedaCamelEndpoint"><messagetype="plaintext"><payload>HellofromCamel!</payload></message><header>
CitrusReferenceGuide
325Camel
![Page 326: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/326.jpg)
<elementname="citrus_camel_route_id"value="newsRoute"/><elementname="citrus_camel_exchange_id"value="ID-local-50532-1402653725341-0-3"/><elementname="citrus_camel_exchange_failed"value="false"/><elementname="citrus_camel_exchange_pattern"value="InOnly"/><elementname="CamelCorrelationId"value="ID-local-50532-1402653725341-0-1"/><elementname="CamelToEndpoint"value="seda://news-feed"/></header></receive>
BesidestheCamelspecificexchangeinformationtheCamelexchangedoesalsoholdsomecustomproperties.ThesepropertiessuchasCamelToEndpointorCamelCorrelationIdarealsoaddedautomaticallytotheCitrusmessageheadersocanexpecttheminareceivemessageaction.
Camelexceptionhandling
Letussupposefollowingroutedefinition:
<camelContextid="camelContext"xmlns="http://camel.apache.org/schema/spring"><routeid="newsRoute"><fromuri="direct:news"/><touri="log:com.consol.citrus.camel?level=INFO"/><touri="seda:news-feed"/><onException><exception>com.consol.citrus.exceptions.CitrusRuntimeException</exception><touri="seda:exceptions"/></onException></route></camelContext>
Theroutehasanexceptionhandlingblockdefinedthatiscalledassoonastheexchangeprocessingendsupinsomeerrororexception.WithCitrusyoucanalsosimulateaexchangeexceptionwhensendingbackasynchronousresponsetoacallingroute.
<sendendpoint="sedaCamelEndpoint"><messagetype="plaintext"><payload>Somethingwentwrong!</payload></message><header><elementname="citrus_camel_exchange_exception"value="com.consol.citrus.exceptions.CitrusRuntimeException"/><elementname="citrus_camel_exchange_exception_message"value="Somethingwentwrong!"/><elementname="citrus_camel_exchange_failed"value="true"/></header>
CitrusReferenceGuide
326Camel
![Page 327: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/327.jpg)
</send>
Thismessageasresponsetotheseda:news-feedroutewouldcauseCameltoentertheexceptionhandlingintheroutedefinition.Theexceptionhandlingisactivatedandcallstheerrorhandlingrouteendpointseda:exceptions.OfcourseCitruswouldbeabletoreceivesuchanexceptionexchangevalidatingtheexceptionhandlingoutcome.
InsuchfailurescenariostheApacheCamelexchangeholdstheexceptioninformation(CamelExceptionCaught)suchascausingexceptionclassanderrormessage.TheseheadersarepresentinanerrorscenarioandcanbevalidatedinCitruswhenreceivingerrormessagesasfollows:
<receiveendpoint="errorCamelEndpoint"><messagetype="plaintext"><payload>Somethingwentwrong!</payload></message><header><elementname="citrus_camel_route_id"value="newsRoute"/><elementname="citrus_camel_exchange_failed"value="true"/><elementname="CamelExceptionCaught"value="com.consol.citrus.exceptions.CitrusRuntimeException:Somethingwentwrong!"/></header></receive>
ThiscompletesthebasicexceptionhandlinginCitruswhenusingtheApacheCamelendpoints.
Camelcontexthandling
IntheprevioussampleswehaveusedtheApacheCamelcontextasSpringbeancontextthatisautomaticallyloadedwhenCitrusstartsup.NowwhenusingasingleCamelcontextinstanceCitrusisabletoautomaticallypickthisCamelcontextforrouteinteraction.IfyouusemorethatoneCamelcontextyouhavetotelltheCitrusendpointcomponentwhichcontexttouse.Theendpointoffersanoptionalattributecalledcamel-context.
<citrus-camel:endpointid="directCamelEndpoint"camel-context="newsContext"endpoint-uri="direct:news"/>
<camelContextid="newsContext"xmlns="http://camel.apache.org/schema/spring">
CitrusReferenceGuide
327Camel
![Page 328: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/328.jpg)
<routeid="newsRoute"><fromuri="direct:news"/><touri="log:com.consol.citrus.camel?level=INFO"/><touri="seda:news-feed"/></route></camelContext>
<camelContextid="helloContext"xmlns="http://camel.apache.org/schema/spring"><routeid="helloRoute"><fromuri="direct:hello"/><touri="log:com.consol.citrus.camel?level=INFO"/><touri="seda:hello"/></route></camelContext>
IntheexampleabpovewehavetwoCamelcontextinstancesloaded.Theendpointhastopickthecontexttousewiththeattributecamel-contextwhichresidestotheSpringbeanidoftheCamelcontext.
Camelrouteactions
SinceCitrus2.4weintroducedsomeCamelspecifictestactionsthatenableeasyinteractionwithCamelroutesandtheCamelcontext.ThetestactionsdofollowaspecificXMLnamespacesowehavetoaddthisnamespacetothetestcasewhenusingtheactions.
<beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:camel="http://www.citrusframework.org/schema/camel/testcase"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.citrusframework.org/schema/camel/testcasehttp://www.citrusframework.org/schema/camel/testcase/citrus-camel-testcase.xsd">
[...]
</beans>
Weaddedaspecialcamelnamespacewithprefixcamel:sonowwecanstarttoaddCameltestactionstothetestcase:
XMLDSL
<testcasename="CamelRouteIT">
CitrusReferenceGuide
328Camel
![Page 329: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/329.jpg)
<actions><camel:create-routes><routeContextxmlns="http://camel.apache.org/schema/spring"><routeid="route_1"><fromuri="direct:test1"/><touri="mock:test1"/></route>
<routeid="route_2"><fromuri="direct:test2"/><touri="mock:test2"/></route></routeContext></camel:create-routes>
<camel:create-routescamel-context="camelContext"><routeContextxmlns="http://camel.apache.org/schema/spring"><route><fromuri="direct:test3"/><touri="mock:test3"/></route></routeContext></camel:create-routes></actions></testcase>
Intheexampleabovewehaveusedthecamel:create-routetestactionthatwillcreatenewCamelroutesatruntimeintheCamelcontext.ThetargetCamelcontextisspecifiedwiththeoptionalcamel-contextattribute.BydefaultCitruswillsearchforaCamelcontextavailableintheSpringbeanapplicationcontext.Removingroutesatruntimeisalsosupported.
XMLDSL
<testcasename="CamelRouteIT"><actions><camel:remove-routescamel-context="camelContext"><routeid="route_1"/><routeid="route_2"/><routeid="route_3"/></camel:remove-routes></actions></testcase>
NextoperationwewilldiscussisthestartandstopofexistingCamelroutes:
XMLDSL
CitrusReferenceGuide
329Camel
![Page 330: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/330.jpg)
<testcasename="CamelRouteIT"><actions><camel:start-routescamel-context="camelContext"><routeid="route_1"/></camel:start-routes>
<camel:stop-routescamel-context="camelContext"><routeid="route_2"/><routeid="route_3"/></camel:stop-routes></actions></testcase>
StartingandstoppingCamelroutesatruntimeisimportantwhentemporarilyCitrusneedtoreceiveamessageonaCamelendpointURI.Wecanstoparoute,useaCitruscamelendpointinsteadforvalidationandstarttherouteafterthetestisdone.ThiswaywencanalsosimulateerrorsandfailurescenariosinaCamelrouteinteraction.
OfcourseallCamelrouteactionsarealsoavailableinJavaDSL.
JavaDSL
@AutowiredprivateCamelContextcamelContext;
@CitrusTestpublicvoidcamelRouteTest()camel().context(camelContext).create(newRouteBuilder(camelContext)@Overridepublicvoidconfigure()throwsExceptionfrom("direct:news").routeId("route_1").autoStartup(false).setHeader("headline",simple("ThisisBIGnews!")).to("mock:news");
from("direct:rumors").routeId("route_2").autoStartup(false).setHeader("headline",simple("Thisisjustarumor!")).to("mock:rumors"););
camel().context(camelContext).start("route_1","route_2");
camel().context(camelContext).stop("route_2");
camel().context(camelContext).remove("route_2");
CitrusReferenceGuide
330Camel
![Page 331: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/331.jpg)
AsyoucanseewehaveaccesstotheCamelroutebuilderthatadds1-nnewCamelroutestothecontext.Afterthatwecanstart,stopandremovetherouteswithinthetestcase.
Camelcontrolbusactions
TheCamelcontrolbuscomponentisagoodwaytoaccessroutestatisticsandroutestatusinformationwithinaCamelcontext.Citrusprovidescontrolbustestactionstoeasilyaccessthecontrolbusoperationsatruntime.
XMLDSL
<testcasename="CamelControlBusIT"><actions><camel:control-bus><camel:routeid="route_1"action="start"/></camel:control-bus>
<camel:control-buscamel-context="camelContext"><camel:routeid="route_2"action="status"/><camel:result>Stopped</camel:result></camel:control-bus>
<camel:control-bus><camel:languagetype="simple">$camelContext.stop()</camel:language></camel:control-bus>
<camel:control-buscamel-context="camelContext"><camel:languagetype="simple">$camelContext.getRouteStatus('route_3')</camel:language<camel:result>Started</camel:result></camel:control-bus></actions></testcase>
Theexampletestcaseshowsthecontrolbusaccess.Camelprovidestwodifferentwaystospecifyoperationsandparameters.Thefirstoptionistheuseofanactionattribute.TheCamelrouteidhastobespecifiedasmandatoryattribute.Asaresultthecontrolbusactionwillbeexecutedonthetargetrouteduringtestruntime.ThiswaywecanalsostartandstopCamelroutesinaCamelcontext.
CitrusReferenceGuide
331Camel
![Page 332: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/332.jpg)
Incaseancontrolbusoperationhasaresultsuchasthestatusactionwecanspecifyacontrolresultthatiscompared.Citruswillraisevalidationexceptionswhentheresultsdiffer.Thesecondoptionforexecutingacontrolbusactionisthelanguageexpression.WecanuseCamellanguageexpressionsontheCamelcontextforaccessingacontrolbusoperation.Alsoherewecandefineanoptionaloutcomeasexpectedresult.
TheJavaDSLalsosupportsthesecontrolbusoperationsasthenextexampleshows:
JavaDSL
@AutowiredprivateCamelContextcamelContext;
@CitrusTestpublicvoidcamelRouteTest()camel().controlBus().route("my_route","start");
camel().controlBus().language(SimpleBuilder.simple("$camelContext.getRouteStatus('my_route')")).result(ServiceStatus.Started);
TheJavaDSLworkswithCamellanguageexpressionbuildersaswellasServiceStatusenumvaluesasexpectedresult.
CitrusReferenceGuide
332Camel
![Page 333: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/333.jpg)
Vert.xeventbussupportVert.xisanapplicationplatformfortheJVMthatprovidesanetworkeventbusforlightweightscalablemessagingsolutions.TheCitrusVert.xcomponentsdoparticipateonthateventbusmessagingasproducerorconsumer.WiththesecomponentsyoucanaccessVert.xinstancesavailableinyournetworkinordertotestthoseVert.xapplicationsinsomeintegrationtestscenario.
NoteTheVert.xcomponentsinCitrusarekeptinaseparateMavenmodule.SoyoushouldaddthemoduleasMavendependencytoyourprojectaccordingly.
<dependency><groupId>com.consol.citrus</groupId><artifactId>citrus-vertx</artifactId><version>2.7.1</version></dependency>
CitrusprovidesaspecialVert.xconfigurationschemathatisusedinourSpringconfigurationfiles.Youhavetoincludethecitrus-vertxnamespaceinyourSpringconfigurationXMLfilesasfollows.
<beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:citrus="http://www.citrusframework.org/schema/config"xmlns:citrus-vertx="http://www.citrusframework.org/schema/vertx/config"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.citrusframework.org/schema/confighttp://www.citrusframework.org/schema/config/citrus-config.xsdhttp://www.citrusframework.org/schema/vertx/confighttp://www.citrusframework.org/schema/vertx/config/citrus-vertx-config.xsd">
[...]
</beans>
NowyouarereadytousetheCitrusVert.xconfigurationelementsusingthecitrus-vertxnamespaceprefix.
ThenextsectionsdiscusssendingandreceivingoperationsontheVert.xeventbuswithCitrus.
CitrusReferenceGuide
333Vertx
![Page 334: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/334.jpg)
Vert.xendpoint
AsusualCitrususesanendpointcomponentinordertospecifysomemessagedestinationtosendandreceivemessagestoandfrom.TheVert.xendpointcomponentisdefinedasfollowsinyourCitrusSpringconfiguration.
<citrus-vertx:endpointid="simpleVertxEndpoint"host="localhost"port="5001"pubSubDomain="false"address="news-feed"/>
<beanid="vertxInstanceFactory"class="com.consol.citrus.vertx.factory.CachingVertxInstanceFactory"
TheendpointholdssomegeneralinformationhowtoaccesstheVert.xeventbus.HostandportvaluesdefinetheVert.xHazelcastclusterhostnameandport.CitrusstartsanewVert.xinstanceusingthiscluster.SoallotherVert.xinstancesconnectedtothisclusterhostwillreceivetheeventbusmessagesfromCitrusduringthetest.Inyourtestcaseyoucanusethisendpointcomponentreferencedbyitsidornameinordertosendandreceivemessagesontheeventbusaddressnews-feed.InVert.xtheeventbusaddressdefinesthedestinationforeventconsumerstolistenon.Asalreadymentionedclusterhostnameandportareoptional,soCitruswilluselocalhostandanewrandomportontheclusterhostifnothingisspecified.
TheVert.xeventbussupportspublish-subscribeandpoint-to-pointmessagecommunicationpatterns.BydefaultthepubSubDomaininCitrusisfalsesotheeventbussenderwillinitiateapoint-to-pointcommunicationontheeventbusaddress.Thismeansthatonlyonesingleconsumerontheeventbusaddresswillreceivethemessage.Iftherearemoreconsumersontheaddressthefirsttocomewinsandreceivesthemessage.Incontrarytothatthepublish-subscribescenariowoulddeliverthemessagetoallavailableconsumersontheeventbusaddresssimultaneously.YoucanenablethepubSubDomainontheVert.xendpointcomponentforthiscommunicationpattern.
TheVert.xendpointneedsainstancefactoryimplementationinordertocreatetheembeddedVert.xinstance.BydefaultthebeannamevertxInstanceFactoryisrecognizedbyallVert.xendpointcomponents.WewilltalkaboutVert.xinstancefactoriesinmoredetaillateroninthischapter.
CitrusReferenceGuide
334Vertx
![Page 335: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/335.jpg)
AsmessagecontentyoucansendandreceiveJSONobjectsorsimplecharactersequencestotheeventbus.LetushavealookatasimplesamplesendingactionthatusesthenewVert.xendpointcomponent:
<sendendpoint="simpleVertxEndpoint"><messagetype="plaintext"><payload>HellofromCitrus!</payload></message></send>
AstheVert.xCitrusendpointisbidirectionalyoucanalsoreceivemessagesfromtheeventbus.
<receiveendpoint="simpleVertxEndpoint"><messagetype="plaintext"><payload>HellofromVert.x!</payload></message><header><elementname="citrus_vertx_address"value="news-feed"/></header></receive>
Citrusautomaticallyaddssomespecialmessageheaderstothemessage,soyoucanvalidatetheVert.xeventbusaddress.ThiscompletesthesimplesendandreceiveoperationsonaVert.xeventbus.NowletsmoveontosynchronousendpointswhereCitruswaitsforareplyontheeventbus.
SynchronousVert.xendpoint
ThesynchronousVert.xeventbusproducersendsamessageandwaitssynchronouslyfortheresponsetoarriveonsomereplyaddressdestination.Thereplyaddressnameisgeneratedautomaticallyandsetintherequestmessageheaderattributessothereceivingcounterpartinthiscommunicationcansenditsreplytothateventbusaddress.ThebasicconfigurationforasynchronousVert.xendpointcomponentlookslikefollows:
<citrus-vertx:sync-endpointid="vertxSyncEndpoint"address="hello"timeout="1000"polling-interval="300"/>
CitrusReferenceGuide
335Vertx
![Page 336: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/336.jpg)
Synchronousendpointspollforsynchronousreplymessagestoarriveontheeventbusreplyaddress.Thepollintervalisanoptionalsettinginordertomanagetheamountofreplymessagehandshakeattempts.Oncetheendpointwasabletoreceivethereplymessagesynchronouslythetestcasecanreceivethereply.Incaseallmessagehandshakeattemptsdofailbecausethereplymessageisnotavailableintimeweraisesometimeouterrorandthetestwillfail.
NoteTheVert.xendpointusestemporaryreplyaddressdestinations.Thetemporaryreplyaddressingeneratedandisonlyusedonceforasinglecommunicationhandshake.Afterthatthereplyaddressisdismissedagain.
WhensendingamessagetothesynchronousVert.xendpointtheproducerwillwaitsynchronouslyfortheresponsemessagetoarriveonthereplyaddress.Youcanreceivethereplymessageinyourtestcaseusingthesameendpointcomponent.Sowehavetwoactionsonthesameendpoint,firstsendthenreceive.
<sendendpoint="vertxSyncEndpoint"><messagetype="plaintext"><payload>HellofromCitrus!</payload></message></send>
<receiveendpoint="vertxSyncEndpoint"><messagetype="plaintext"><payload>ThisisthereplyfromVert.x!</payload></message></receive>
Inthelastsectionwesawthatsynchronouscommunicationisbasedonreplymessagesontemporaryreplyeventbusaddress.WesawthatCitrusisabletosendmessagestoeventbusaddressandwaitforreplymessagestoarrive.Thisnextsectiondealswiththesamesynchronouscommunication,butsendandreceiverolesareswitched.NowCitrusreceivesamessageandhastosendareplymessagetoatemporaryreplyaddress.
WehandlethissynchronouscommunicationwiththesamesynchronousVert.xendpointcomponent.Onlydifferenceisthatweinitiallystartthecommunicationbyreceivingamessagefromtheendpoint.KnowingthisCitrusisabletosendasynchronousresponseback.Againjustusethesameendpointreferenceinyourtestcase.Thehandlingofthetemporaryreplyaddressisdoneautomaticallybehindthescenes.Sowehaveagaintwoactionsinourtestcase,butthistimefirstreceivethensend.
<receiveendpoint="vertxSyncEndpoint">
CitrusReferenceGuide
336Vertx
![Page 337: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/337.jpg)
<messagetype="plaintext"><payload>HellofromVert.x!</payload></message></receive>
<sendendpoint="vertxSyncEndpoint"><messagetype="plaintext"><payload>ThisisthereplyfromCitrus!</payload></message></send>
ThesynchronousmessageendpointforVert.xeventbuscommunicationwillhandleallreplyaddressdestinationsandprovidethosebehindthescenes.
Vert.xinstancefactory
CitrusstartsanembeddedVert.xinstanceatruntimeinordertoparticipateintheVert.xcluster.WithinthisclustermultipleVert.xinstancesareconnectedviatheeventbus.ForstartingtheVert.xeventbusCitrususesaclusterhostnameandportdefinition.Youcancustomizethisclusterhostinordertoconnecttoaveryspecialclusterinyournetwork.
NowCitrusneedstomanagetheVert.xinstancescreatedduringthetestrun.BydefaultCitruswilllookforainstancefactorybeannamedvertxInstanceFactory.Youcanchoosethefactoryimplementationtouseinyourproject.BydefaultyoucanusethecachingfactoryimplementationthatcachestheVert.xinstancessowedonotconnectmorethanoneVert.xinstancetothesameclusterhost.Citrusoffersfollowinginstancefactoryimplementations:
com.consol.citrus.vertx.factory.CachingVertxInstanceFactory-defaultimplementationthatreusestheVert.xinstancebasedongivenclusterhostandport.Withthisimplementationweensureto
connectasingleCitrusVert.xinstancetoaclusterhost.
com.consol.citrus.vertx.factory.SingleVertxInstanceFactory-createsasingleVert.xinstanceandreusesthisinstanceforallendpoints.YoucanalsosetyourverycustomVert.xinstanceviaconfiguration
forcustomVert.xinstantiation.
CitrusReferenceGuide
337Vertx
![Page 338: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/338.jpg)
TheinstancefactoryimplementationsdoimplementtheVertxInstanceFactoryinterface.Soyoucanalsoprovideyourveryspecialimplementation.BydefaultCitruslooksforabeannamedvertxInstanceFactorybutyoucanalsodefineyourveryspecialfactoryimplementationonmanendpointcomponent.TheVert.xinstancefactoryissetontheVert.xendpointasfollows:
<citrus-vertx:endpointid="vertxHelloEndpoint"address="hello"vertx-factory="singleVertxInstanceFactory"/>
<beanid="singleVertxInstanceFactory"class="com.consol.citrus.vertx.factory.SingleVertxInstanceFactory"/>
CitrusReferenceGuide
338Vertx
![Page 339: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/339.jpg)
MailsupportSendingandreceivingmailsisthenextinterestwearegoingtotalkabout.WhendealingwithmailcommunicationyoumostcertainlyneedtointeractwithsomesortofIMAPorPOPmailserver.ButinCitruswedonotwanttomanagemailsinapersonalinbox.Wejustneedtobeabletoexchangemailmessagesthepersistinginauserinboxisnotpartofourbusiness.
ThisiswhyCitrusprovidesjustaSMTPmailserverwhichacceptsmailmessagesfromclients.OncetheSMTPserverhasacceptedanincomingmailitforwardsthosedatatotherunningtestcase.Inthetestcaseyoucanreceivetheincomingmailmessageandperformmessagevalidationasusual.ThemailsendingpartiseasyasCitrusoffersamailclientthatconnectstosomeSMTPserverforsendingmailstotheoutsideworld.
NoteThemailcomponentsinCitrusarekeptinaseparateMavenmodule.SoyoushouldcheckthatthemoduleisavailableasMavendependencyinyourproject
<dependency><groupId>com.consol.citrus</groupId><artifactId>citrus-mail</artifactId><version>2.7.1</version></dependency>
AsusualCitrusprovidesacustomizedmailconfigurationschemathatisusedinSpringconfigurationfiles.Simplyincludethecitrus-mailnamespaceintheconfigurationXMLfilesasfollows.
<beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:citrus="http://www.citrusframework.org/schema/config"xmlns:citrus-mail="http://www.citrusframework.org/schema/mail/config"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.citrusframework.org/schema/confighttp://www.citrusframework.org/schema/config/citrus-config.xsdhttp://www.citrusframework.org/schema/mail/confighttp://www.citrusframework.org/schema/mail/config/citrus-mail-config.xsd">
[...]
</beans>
CitrusReferenceGuide
339Mail
![Page 340: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/340.jpg)
NowyouarereadytousethecustomizedHttpconfigurationelementswiththecitrus-mailnamespaceprefix.
ReadthenextsectioninordertofindoutmoreaboutthemailmessagesupportinCitrus.
Mailclient
Themailsendingpartisquiteeasyandstraightforward.WejustneedtosendamailmessagetosomeSMTPserver.SoCitrusprovidesamailclientthatsendsoutmailmessages.
<citrus-mail:clientid="simpleMailClient"host="localhost"port="25025"/>
ThisishowaCitrusmailclientcomponentisdefinedintheSpringapplicationcontext.Youcanusethisclientreferencedbyitsidornameinyourtestcaseinamessagesendingaction.TheclientdefinesahostandportattributewhichshouldconnecttheclienttosomeSMTPserverinstance.
Weallknowmailmessagecontents.Themailmessagehassomegeneralpropertiessetbytheuser:
from:Themessagesendermailaddressto:Themessagerecipientmailaddress.Youcanaddmultiplerecipientsbyusingacommaseparatedlist.cc:Copyrecipientmailaddress.Youcanaddmultiplerecipientsbyusingacommaseparatedlist.bcc:Blindcopyrecipientmailaddress.Youcanaddmultiplerecipientsbyusingacommaseparatedlist.subject:Somesubjectusedasmailheadline.
Asatesteryouareabletosetthesepropertiesinyourtestcase.CitrusdefinesaXMLmailmessagerepresentationthatyoucanuseinsideyoursendaction.Letushavealookatthis:
<sendendpoint="simpleMailClient"><message><payload><mail-messagexmlns="http://www.citrusframework.org/schema/mail/message"><from>[email protected]</from>
CitrusReferenceGuide
340Mail
![Page 341: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/341.jpg)
<to>[email protected]</to><cc></cc><bcc></bcc><subject>Thisisatestmailmessage</subject><body><contentType>text/plain;charset=utf-8</contentType><content>HelloCitrusmailserver!</content></body></mail-message></payload></message></send>
ThebasicXMLmailmessagerepresentationdefinesalistofbasicmailpropertiessuchasfrom,toorsubject.InadditiontothatwedefineatextbodywhichiseitherplaintextorHTML.Youcanspecifythecontenttypeofthemailbodyveryeasy(e.g.text/plainortext/html).BydefaultCitrususestext/plaincontenttype.
Nowwhendealingwithmailmessagesyouoftencometousemultipartstructuresforattachments.InCitrusyoucandefineattachmentcontentasbase64charactersequence.TheCitrusmailclientwillautomaticallycreateapropermultipartmailmimemessageusingthecontenttypesandbodypartsspecified.
<sendendpoint="simpleMailClient"><message><payload><mail-messagexmlns="http://www.citrusframework.org/schema/mail/message"><from>[email protected]</from><to>[email protected]</to><cc></cc><bcc></bcc><subject>Thisisatestmailmessage</subject><body><contentType>text/plain;charset=utf-8</contentType><content>HelloCitrusmailserver!</content><attachments><attachment><contentType>text/plain;charset=utf-8</contentType><content>Thisisattachmentdata</content><fileName>attachment.txt</fileName></attachment></attachments></body></mail-message></payload></message></send>
CitrusReferenceGuide
341Mail
![Page 342: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/342.jpg)
Thatcompletesthebasicmailclientcapabilities.Butwaitwehavenottalkedabouterrorscenarioswheremailcommunicationresultsinerror.Whenrunningintomailerrorscenarioswehavetohandletheerrorrespectivelywithexceptionhandling.WhenthemailserverrespondedwitherrorsCitruswillraisemailexceptionsautomaticallyandyourtestcasefailsaccordingly.
Asatesteryoucancatchandassertthesemailexceptionsverifyingyourerrorscenario.
<assertexception="org.springframework.mail.MailSendException"><when><sendendpoint="simpleMailClient"><message><payload><mail-messagexmlns="http://www.citrusframework.org/schema/mail/message">[...]</mail-message></payload></message></send></when><assert/>
WeasserttheMailSendExceptionfromSpringtobethrownwhilesendingthemailmessagetotheSMTPserver.Withexceptionmessagevalidationyouareabletoexpectveryspecificmailsenderrorsontheclientside.Thisishowyoucanhandlesomesortoferrorsituationreturnedbythemailserver.SpeakingofmailserversweneedtoalsotalkaboutprovidingamailserverendpointinCitrusforclients.Thisispartofournextsection.
Mailserver
Consumingmailmessagesisamorecomplicatedtaskasweneedtohavesomesortofserverthatclientscanconnectto.InyourmailclientsoftwareyoutypicallypointtosomeIMAPorPOPinboxandreceivemailsfromthatendpoint.InCitruswedonotwanttomanageawholepersonalmailinboxsuchasIMAPorPOPwouldprovide.WejustneedaSMTPserverendpointforclientstosendmailsto.TheSMTPserveracceptsmailmessagesandforwardsthosetoarunningtestcaseforfurthervalidation.
NoteWehavenouserinboxwhereincomingmailsarestored.Themailserverjustforwardsincomingmailstotherunningtestforvalidation.Afterthetesttheincomingmailmessageisgone.
CitrusReferenceGuide
342Mail
![Page 343: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/343.jpg)
AndthisisexactlywhattheCitrusmailserveriscapableof.TheserverisaverylightweightSMTPserver.AllincomingmailclientconnectionsareacceptedbydefaultandthemaildataisconvertedintoaCitrusXMLmailinterfacerepresentation.TheXMLmailmessageisthenpassedtotherunningtestforvalidation.
LetushavealookattheCitrusmailservercomponentandhowyoucanaddittotheSpringapplicationcontext.
<citrus-mail:serverid="simpleMailServer"port="25025"auto-start="true"/>
Themailservercomponentreceivesseveralpropertiessuchasportorauto-start.CitrusstartsainmemorySMTPserverthatclientscanconnectto.
InyourtestcaseyoucanthenreceivetheincomingmailmessagesontheserverinordertoperformthewellknownXMLvalidationmechanismswithinCitrus.Themessageheaderandthepayloadcontainallmailinformationsoyoucanverifythecontentwithexpectedtemplatesasusual:
<receiveendpoint="simpleMailServer"><message><payload><mail-messagexmlns="http://www.citrusframework.org/schema/mail/message"><from>[email protected]</from><to>[email protected]</to><cc></cc><bcc></bcc><subject>Thisisatestmailmessage</subject><body><contentType>text/plain;charset=utf-8</contentType><content>HelloCitrusmailserver!</content></body></mail-message></payload><header><elementname="citrus_mail_from"value="[email protected]"/><elementname="citrus_mail_to"value="[email protected]"/><elementname="citrus_mail_subject"value="Thisisatestmailmessage"/><elementname="citrus_mail_content_type"value="text/plain;charset=utf-8"/></header></message></receive>
CitrusReferenceGuide
343Mail
![Page 344: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/344.jpg)
Thegeneralmailpropertiessuchasfrom,to,subjectareavailableaselementsinthemailpayloadandinthemessageheaderinformation.ThemessageheadernamesdostartwithacommonCitrusmailprefixcitrus_mail.Followingfromthatyoucanverifythesespecialmailmessageheadersinyourtestasshownabove.Citrusoffersfollowingmailheaders:
citrus_mail_fromcitrus_mail_tocitrus_mail_cccitrus_mail_bcccitrus_mail_subjectcitrus_mail_replyTocitrus_mail_date
InadditiontothatCitrusconvertstheincomingmaildatatoaspecialXMLmailrepresentationwhichispassedasmessagepayloadtothetest.Themailbodypartsarerepresentedasbodyandoptionalattachmentelements.AsthisisplainXMLyoucanverifythemailmessagecontentasusualusingCitrusvariables,functionsandvalidationmatchers.
RegardlessofhowthemailmessagehaspassedthevalidationtheCitrusSMTPmailserverwillautomaticallyrespondwithsuccesscodes(SMTP250OK)tothecallingclient.ThisisthebasicCitrusmailserverbehaviorwhereallclientconnectionsareacceptedanallmailmessagesarerespondedwithSMTP250OKresponsecodes.
Nowinmoreadvancedusagescenariosthetestermaywanttocontrolthemailcommunicationoutcome.UsercanforcesomeerrorscenarioswheremailclientsarenotacceptedormailcommunicationshouldfailwithsomeSMTPerrorstateforinstance.
Byusingamoreadvancedmailserversetupthetestergetsmorepowertosendingbackmailserverresponsecodestothemailclient.Justusetheadvancedmailadapterimplementationinyourmailservercomponentconfiguration:
<citrus-mail:serverid="advancedMailServer"auto-accept="false"split-multipart="true"port="25025"auto-start="true"/>
CitrusReferenceGuide
344Mail
![Page 345: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/345.jpg)
Wehavedisabledtheauto-acceptmodeonthemailserver.Thismeansthatwehavetodosomeadditionalstepsinyourtestcasetoaccepttheincomingmailmessagefirst.Sowecandecideinourtestcasewhethertoacceptordeclinetheincomingmailmessageforamorepowerfultest.Youaccept/declineamailmessagewithaspecialXMLacceptrequest/responseexchangeinyourtestcase:
<receiveendpoint="advancedMailServer"><message><payload><accept-requestxmlns="http://www.citrusframework.org/schema/mail/message"><from>[email protected]</from><to>[email protected]</to></accept-request></payload></message></receive>
Sobeforereceivingtheactualmailmessagewereceivethissimpleaccept-requestinourtest.Theacceptrequestgivesusthemessagefromandtoresourcesofthemailmessage.Nowthetestdecidestoalsodeclineamailclientconnection.Youcansimulatethattheserverdoesnotacceptthemailclientconnectionbysendingbackanegativeacceptresponse.
<sendendpoint="advancedMailServer"><message><payload><accept-responsexmlns="http://www.citrusframework.org/schema/mail/message"><accept>true</accept></accept-response></payload></message></send>
Dependingontheacceptoutcomethemailclientwillreceiveanerrorresponsewithpropererrorcodes.Ifyouacceptthemailmessagewithapositiveacceptresponsethenextstepinyourtestreceivestheactualmailmessageaswehaveseenitbeforeinthischapter.
Nowbesidesnotacceptingamailmessageinthefirstplaceyoucanalssimulateanothererrorscenariowiththemailserver.InthisscenariothemailservershouldrespondwithsomesortofSMTPerrorcodeafteracceptingthemessage.Thisisdonewithaspecialmailresponsemessagelikethis:
CitrusReferenceGuide
345Mail
![Page 346: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/346.jpg)
<receiveendpoint="advancedMailServer"><message><payload><mail-messagexmlns="http://www.citrusframework.org/schema/mail/message"><from>[email protected]</from><to>[email protected]</to><cc></cc><bcc></bcc><subject>Thisisatestmailmessage</subject><body><contentType>text/plain;charset=utf-8</contentType><content>HelloCitrusmailserver!</content></body></mail-message></payload></message></receive>
<sendendpoint="advancedMailServer"><message><payload><mail-responsexmlns="http://www.citrusframework.org/schema/mail/message"><code>443</code><message>Failed!</message></mail-response></payload></message></send>
Asyoucanseefromtheexampleabovewefirstaccepttheconnectionandreceivethemailcontentasusual.Nowthetestreturnsanegativemailresponsewithsomeerrorcodereasonset.TheCitrusSMTPcommunicationwillthenfailandthecallingmailclientreceivestherespectiveerror.
IfyouskipthenegativemailresponsetheserverwillautomaticallyresponsewithpositiveSMTPresponsecodestothecallingclient.
CitrusReferenceGuide
346Mail
![Page 347: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/347.jpg)
ArquilliansupportArquillianisawellknownintegrationtestframeworkthatcomeswithagreatfeaturesetwhenitcomestoJavaEEtestinginsideofafullqualifiedapplicationserver.WithArquiliianyoucandeployyourJavaEEservicesinarealapplicationserverofyourchoiceandexecutethetestsinsidetheapplicationserverboundaries.ThismakesitveryeasytotestyourJavaEEservicesinscopewithproperJNDIresourceallocationandotherresourcesprovidedbytheapplicationserver.CitrusisabletoconnectwiththeArquilliantestcase.SpeakinginmoredetailyourArquilliantestisabletouseaCitrusextensioninordertousetheCitrusfeaturesetinsidetheArquillianboundaries.
ReadthenextsectioninordertofindoutmoreabouttheCitrusArquillianextension.
CitrusArquillianextension
ArquillianoffersafinemechanismforextensionsaddingfeaturestotheArquilliantestsetupandtestexecution.TheCitrusextensionrespectivelyaddsCitrusframeworkinstancecreationandCitrustestexecutiontotheArquillianworld.Firstofallletshavealookattheextensiondescriptorpropertiessettableviaarquillian.xml:
<extensionqualifier="citrus"><propertyname="citrusVersion">2.7.1</property><propertyname="autoPackage">true</property><propertyname="suiteName">citrus-arquillian-suite</property></extension>
TheCitrusextensionusesaspecificqualifiercitrusfordefiningpropertiesinsidetheArquilliandescriptor.Followingpropertiesaresettableincurrentversion:
citrusVersion:TheexplicitversionofCitrusthatshouldbeused.Besuretohavethesamelibraryversionavailableinyourproject(e.g.asMavendependency).Thispropertyisoptional.
Bydefaulttheextensionjustusesthelateststableversion.
autoPackage:Whentrue(defaultsetting)theextensionwillautomaticallyaddCitruslibrariesandalltransitivedependenciestothetestdeployment.ThisautomaticallyenablesyoutousetheCitrusAPIinsidetheArquilliantest
evenwhenthetestisexecutedinsidetheapplicationcontainer.
CitrusReferenceGuide
347Arquillian
![Page 348: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/348.jpg)
suiteName:ThisoptionalsettingdefinesthenameofthetestsuitethatisusedfortheCitrustestrun.Whenusingbefore/aftersuitefunctionalityinCitrusthissettingmightbeofinterest.configurationClass:FullqualifiedJavaclassnameofcustomizedCitrusSpringbeanconfigurationtousewhenloadingtheCitrusSpringapplicationcontext.Asauseryoucandefineacustomconfigurationclassthatmust
beasubclassofcom.consol.citrus.config.CitrusSpringConfig.Whenspecifiedthecustomclassisloadedotherwisethedefaultcom.consol.citrus.config.CitrusSpringConfigisloadedtosetuptheSpringapplicationcontext.
NowthatwehaveaddedtheextensiondescriptorwithallpropertiesweneedtoaddtherespectiveCitrusArquillianextensionaslibrarytoourproject.ThisisdoneviaMaveninyourproject'sPOMfileasnormaldependency:
<dependency><groupId>com.consol.citrus</groupId><artifactId>citrus-arquillian</artifactId><version>2.7.1</version><scope>test</scope></dependency>
NoweverythingissetuptouseCitruswithinArquillian.LetsuseCitrusfunctionalityinaArquilliantestcase.
Clientsidetesting
Arquillianseparatesclientandcontainersidetesting.Whenusingclientsidetestingthetestcaseisexecutedoutsideoftheapplicationcontainerdeployment.ThismeansthatyourtestcasehasnodirectaccesstocontainermanagedresourcessuchasJNDIresources.Ontheplussideitisnotnecessarytoincludeyourtestinthecontainerdeployment.Thetestcaseinteractswiththecontainerdeploymentasanormalclientwoulddo.Letshavealookatafirstexample:
@RunWith(Arquillian.class)@RunAsClientpublicclassEmployeeResourceTest
@CitrusFrameworkprivateCitruscitrusFramework;
CitrusReferenceGuide
348Arquillian
![Page 349: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/349.jpg)
@ArquillianResourceprivateURLbaseUri;
privateStringserviceUri;
@DeploymentpublicstaticWebArchivecreateDeployment()returnShrinkWrap.create(WebArchive.class).addClasses(RegistryApplication.class,EmployeeResource.class,Employees.class,Employee.class,EmployeeRepository.class);
@BeforepublicvoidsetUp()throwsMalformedURLExceptionserviceUri=newURL(baseUri,"registry/employee").toExternalForm();
@Test@CitrusTestpublicvoidtestCreateEmployeeAndGet(@CitrusResourceTestDesignerdesigner)designer.send(serviceUri).message(newHttpMessage("name=Penny&age=20").method(HttpMethod.POST).contentType(MediaType.APPLICATION_FORM_URLENCODED));
designer.receive(serviceUri).message(newHttpMessage().statusCode(HttpStatus.NO_CONTENT));
designer.send(serviceUri).message(newHttpMessage().method(HttpMethod.GET).accept(MediaType.APPLICATION_XML));
designer.receive(serviceUri).message(newHttpMessage(""+""+"20"+"Penny"+""+"").statusCode(HttpStatus.OK));
citrusFramework.run(designer.build());
FirstofallweusethebasicArquillianJUnittestrunner@RunWith(Arquillian.class)incombinationwiththe@RunAsClientannotationtellingArquillianthatthisisaclientsidetestcase.AsthisisausualArquilliantestcasewehaveaccesstoArquillianresources
CitrusReferenceGuide
349Arquillian
![Page 350: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/350.jpg)
thatautomaticallygetinjectedsuchasthebaseuriofthetestdeployment.ThetestdeploymentisawebdeploymentcreatedviaShrinkWrap.WeaddtheapplicationspecificclassesthatbuildourremoteRESTfulservicethatwewouldliketotest.
TheCitrusArquillianextensionisabletosetupaproperCitrustestenvironmentinthebackground.AsaresultthetestcasecanreferenceaCitrusframeworkinstancewiththe@CitrusFrameworkannotation.WewillusethisinstanceofCitruslateronwhenitcomestoexecutetheCitrustestinglogic.
NowecanfocusonwritingatestmethodwhichisagainnothingbutanormalJUnittestmethod.TheCitrusextensiontakescareoninjectingthe@CitrusResourceannotatedmethodparameter.WiththisCitrustestdesignerinstancewecanbuildaCitrustestlogicforsendingandreceivingmessagesviaHttpinordertocalltheremoteRESTfulemployeeserviceofourtestdeployment.TheHttpendpointuriisinjectedviaArquillianandweareabletocalltheremoteserviceasaclient.
TheCitrustestdesignerprovidesJavaDSLmethodsforbuildingthetestlogic.Pleasenotethatthedesignerwillaggregateallactionssuchassendorreceiveuntilthedesigneriscalledtobuildthetestcasewithbuild()methodinvocation.TheresultingtestcaseobjectcanbeexecutedbytheCitrusframeworkinstancewithrun()method.
WhentheCitrustestcaseisexecutedthemessagesaresentoverthewire.TherespectiveresponsemessageisreceivedwithwellknownCitrusreceivemessagelogic.Wecanvalidatetheresponsemessagesaccordinglyandmakesuretheclientcallwasdoneright.IncasesomethinggoeswrongwithinCitrustestexecutiontheframeworkwillraiseexceptionsaccordingly.AsaresulttheJUnittestmethodissuccessfulorfailedwitherrorscomingfromCitrustestexecution.
ThisishowCitrusandArquilliancaninteractinatestscenariowherethetestdeploymentismanagedbyArquillianandtheclientsideactionstakeplacewithinCitrus.ThisisagreatwaytocombinebothframeworkswithCitrusbeingabletocalldifferentserviceAPIendpointsinadditionwithvalidatingtheoutcome.Thiswasaclientsidetestcasewherethetestlogicwasexecutedoutsideoftheapplicationcontainer.Arquillianalsosupportscontainerremotetestcaseswherewehavedirectaccesstocontainermanagedresources.ThefollowingsectiondescribeshowthisworkswithCitrus.
Containersidetesting
InprevioussectionswehaveseenhowtocombineCitruswithArquillianinaclientsidetestcase.Thisisthewaytogoforalltestcasesthatdonotneedtohaveaccessoncontainermanagedresources.Letshavealookatasamplewherewewanttogain
CitrusReferenceGuide
350Arquillian
![Page 351: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/351.jpg)
accesstoaJMSqueueandconnectionmanagedbytheapplicationcontainer.
@RunWith(Arquillian.class)publicclassEchoServiceTest
@CitrusFrameworkprivateCitruscitrusFramework;
@Resource(mappedName="jms/queue/test")privateQueueechoQueue;
@Resource(mappedName="/ConnectionFactory")privateConnectionFactoryconnectionFactory;
privateJmsSyncEndpointjmsSyncEndpoint;
@Deployment@OverProtocol("Servlet3.0")publicstaticWebArchivecreateDeployment()throwsMalformedURLExceptionreturnShrinkWrap.create(WebArchive.class).addClasses(EchoService.class);
@BeforepublicvoidsetUp()JmsSyncEndpointConfigurationendpointConfiguration=newJmsSyncEndpointConfiguration();endpointConfiguration.setConnectionFactory(newSingleConnectionFactory(connectionFactory));endpointConfiguration.setDestination(echoQueue);jmsSyncEndpoint=newJmsSyncEndpoint(endpointConfiguration);
@AfterpublicvoidcleanUp()closeConnections();
@Test@CitrusTestpublicvoidshouldBeAbleToSendMessage(@CitrusResourceTestDesignerdesigner)throwsExceptionStringmessageBody="ping";
designer.send(jmsSyncEndpoint).messageType(MessageType.PLAINTEXT).message(newJmsMessage(messageBody));
designer.receive(jmsSyncEndpoint).messageType(MessageType.PLAINTEXT).message(newJmsMessage(messageBody));
citrusFramework.run(designer.build());
CitrusReferenceGuide
351Arquillian
![Page 352: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/352.jpg)
privatevoidcloseConnections()((SingleConnectionFactory)jmsSyncEndpoint.getEndpointConfiguration().getConnectionFactory()).destroy();
AsyoucanseethetestcaseaccessestwocontainermanagedresourcesviaJNDI.ThisisaJMSqueueandaJMSconnectionthatgetautomaticallyinjectedasresources.InabeforetestannotatedmethodwecanusetheseresourcestobuildupaproperCitrusJMSendpoint.InsidethetestmethodwecanusetheJMSendpointforsendingandreceivingJMSmessagesviaCitrus.Asusualresponsemessagesreceivedarevalidatedandcomparedtoanexpectedmessage.AsusualweusetheCitrusTestDesignermethodparameterthatisinjectedbytheframework.ThedesignerisabletobuildCitrustestlogicwithJavaDSLmethods.Oncethecompletetestisdesignedwecanbuildthetestcaseandrunthetestcasewiththeframeworkinstance.AfterthetestweshouldclosetheJMSconnectioninordertoavoidexceptionswhentheapplicationcontainerisshuttingdownafterthetest.
Thetestisnowpartofthetestdeploymentandisexecutedwithintheapplicationcontainerboundaries.AsusualwecanusetheCitrusextensiontoautomaticallyinjecttheCitrusframeworkinstanceaswellastheCitrustestbuilderinstanceforbuildingtheCitrustestlogic.
ThisishowtocombineCitrusandArquillianinordertobuildintegrationtestsonJavaEEservicesinarealapplicationcontainerenvironment.WithCitrusyouareabletosetupmorecomplextestscenarioswithsimulatedservicessuchasmailorftpservers.WecanbuildCitrusendpointswithcontainermanagedresources.
Testrunners
IntheprevioussectionswehaveusedtheCitrusTestDesignerinordertoconstructaCitrustestcasetoexecutewithintheArquillianboundaries.ThenatureofthetestdesigneristoaggregateallJavaDSLmethodcallsinordertobuildacompleteCitrustestcasebeforeexecutionisdoneviatheCitrusframework.ThisapproachcancausesomeunexpectedbehaviorwhenmixingtheCitrusJavaDSLmethodcallswithArquilliantestlogic.LetsdescribethisbyhavingalookatanexamplewherethmixtureoftestdesignerandpureJavatestlogiccausesunseenproblems.
@Test@CitrusTest
CitrusReferenceGuide
352Arquillian
![Page 353: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/353.jpg)
publicvoidtestDesignRuntimeMixture(@CitrusResourceTestDesignerdesigner)throwsExceptiondesigner.send(serviceUri).message(newHttpMessage("name=Penny&age=20").method(HttpMethod.POST).contentType(MediaType.APPLICATION_FORM_URLENCODED));
designer.receive(serviceUri).message(newHttpMessage()).statusCode(HttpStatus.NO_CONTENT));
EmployeetestEmployee=employeeService.findEmployee("Penny");employeeService.addJob(testEmployee,"waitress");
designer.send(serviceUri).message(newHttpMessage().method(HttpMethod.GET).accept(MediaType.APPLICATION_XML));
designer.receive(serviceUri).message(newHttpMessage(""+""+"20"+"Penny"+""+"waitress"+""+""+"")).statusCode(HttpStatus.OK));
citrusFramework.run(designer.build());
AsyoucanseeinthisexamplewecreateanewEmployeenamedPennyviatheHttpRESTAPIonourservice.WedothiswithCitrusHttpsendandreceivemessagelogic.Oncethisisdonewewouldliketoaddajobdescriptiontotheemployee.WeuseaserviceinstanceofEmployeeServicewhichisaserviceofourtestdomainthatisinjectedtotheArquilliantestascontainerJEEresource.Firstofallwefindtheemployeeobjectandthenweaddsomejobdescriptionusingtheservice.NowasaresultwewouldliketoreceivetheemployeeasXMLrepresentationviaaRESTservicecallwithCitrusandweexpectthejobdescriptiontobepresent.
ThiscombinationofCitrusJavaDSLmethodsandservicecalllogicwillnotworkwithTestDesigner.ThisisbecausetheCitrustestlogicisnotexecutedimmediatelybutaggregatedtotheveryendwherethedesigneriscalledtobuildthetestcase.ThecombinationofCitrusdesigntimeandJavatestruntimeistricky.
CitrusReferenceGuide
353Arquillian
![Page 354: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/354.jpg)
FortunatelywehavesolvedthisissuewithprovidingaseparateTestRunnercomponent.ThetestrunnerprovidesnearlythesameJavaDSLmethodsforconstructingCitrustestlogicasthetestdesigner.ThedifferencethoughisthatthetestlogicisexecutedimmediatelywhencallingtheJavaDSLmethods.SofollowingfromthatwecanmixCitrusJavaDSLcodewithtestruntimelogicasexpected.Seehowthislookslikewithourexample:
@Test@CitrusTestpublicvoidtestDesignRuntimeMixture(@CitrusResourceTestRunnerrunner)throwsExceptionrunner.send(builder->builder.endpoint(serviceUri).message(newHttpMessage("name=Penny&age=20").method(HttpMethod.POST).contentType(MediaType.APPLICATION_FORM_URLENCODED)));
runner.receive(builder->builder.endpoint(serviceUri).message(newHttpMessage().statusCode(HttpStatus.NO_CONTENT)));
EmployeetestEmployee=employeeService.findEmployee("Penny");employeeService.addJob(testEmployee,"waitress");
runner.send(builder->builder.endpoint(serviceUri).message(newHttpMessage().method(HttpMethod.GET).accept(MediaType.APPLICATION_XML)));
runner.receive(builder->builder.endpoint(serviceUri).message(newHttpMessage(""+""+"20"+"Penny"+""+"waitress"+""+""+"").statusCode(HttpStatus.OK)));
Thetestlogichasnotchangedsignificantly.WeusetheCitrusTestRunnerasmethodinjectedparameterinsteadoftheTestDesigner.Andthisisprettymuchthetrick.NowtheJavaDSLmethodsdoexecutetheCitrustestlogicimmediately.ThisiswhythesyntaxoftheCitrusJavaDSLmethodshavechangedalittlebit.Wenowusea
CitrusReferenceGuide
354Arquillian
![Page 355: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/355.jpg)
anonymousinterfaceimplementationforconstructingthesend/receivetestactionlogic.AsaresultwecanusetheCitrusJavaDSLasnormalcodeandwecanmixtheruntimeJavalogicaseachstatementisexecutedimmediately.
WithJava8lambdaexpressionsourcodelooksevenmorestraightforwardandlessverboseaswecanskiptheanonymousinterfaceimplementations.WithJava8youcanwritethesametestlikethis:
@Test@CitrusTestpublicvoidtestDesignRuntimeMixture(@CitrusResourceTestRunnerrunner)throwsExceptionrunner.send(builder->builder.endpoint(serviceUri).message(newHttpMessage("name=Penny&age=20").method(HttpMethod.POST).contentType(MediaType.APPLICATION_FORM_URLENCODED));
runner.receive(builder->builder.endpoint(serviceUri).message(newHttpMessage().statusCode(HttpStatus.NO_CONTENT));
EmployeetestEmployee=employeeService.findEmployee("Penny");employeeService.addJob(testEmployee,"waitress");
runner.send(builder->builder.endpoint(serviceUri).message(newHttpMessage().method(HttpMethod.GET).accept(MediaType.APPLICATION_XML));
runner.receive(builder->builder.endpoint(serviceUri).message(newHttpMessage(""+""+"20"+"Penny"+""+"waitress"+""+""+"").statusCode(HttpStatus.OK));
CitrusReferenceGuide
355Arquillian
![Page 356: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/356.jpg)
DockersupportCitrusprovidesconfigurationcomponentsandtestactionsforinteractionwithaDockerdaemon.TheCitrusdockerclientcomponentwillexecuteDockercommandsforcontainermanagementsuchasstart,stop,build,inspectandsoon.TheDockerclientbydefaultusestheDockerremoteRESTAPI.AsauseryoucanexecuteDockercommandsaspartofaCitrustestandvalidatepossiblecommandresults.
NoteTheDockertestcomponentsinCitrusarekeptinaseparateMavenmodule.IfnotalreadydonesoyouhavetoincludethemoduleasMavendependencytoyourproject
<dependency><groupId>com.consol.citrus</groupId><artifactId>citrus-docker</artifactId><version>2.7.1</version></dependency>
Citrusprovidesa"citrus-docker"configurationnamespaceandschemadefinitionforDockerrelatedcomponentsandactions.IncludethisnamespaceintoyourSpringconfigurationinordertousetheCitrusDockerconfigurationelements.ThenamespaceURIandschemalocationareaddedtotheSpringconfigurationXMLfileasfollows.
<beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:citrus-docker="http://www.citrusframework.org/schema/docker/config"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.citrusframework.org/schema/docker/confighttp://www.citrusframework.org/schema/docker/config/citrus-docker-config.xsd">
[...]
</beans>
AfterthatyouareabletousecustomizedCitrusXMLelementsinordertodefinetheSpringbeans.
Dockerclient
CitrusReferenceGuide
356Docker
![Page 357: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/357.jpg)
CitrusoperateswiththeDockerremoteRESTAPIinordertointeractwiththeDockerdaemon.TheDockerclientisdefinedasSpringbeancomponentintheconfigurationasfollows:
<citrus-docker:clientid="dockerClient"/>
TheDockerclientcomponentaboveisusingalldefaultconfigurationvalues.BydefaultCitrusissearchingthesystempropertiesaswellasenvironmentvariablesfordefaultDockersettingssuchas:
DOCKER_HOST="tcp://localhost:2376"DOCKER_CERT_PATH="~/.docker/machine/machines/default"DOCKER_TLS_VERIFY="1"DOCKER_MACHINE_NAME="default"
IncasethesesettingsarenotsettableinyourenvironmentyoucanalsouseexplicitsettingsintheDockerclientcomponent:
<citrus-docker:clientid="dockerClient"url="tcp://localhost:2376"version="1.20"username="user"password="s!cr!t"email="[email protected]"registry="https://index.docker.io/v1/"cert-path="/path/to/some/cert/directory"config-path="/path/to/some/config/directory"/>
NowCitrusisabletoaccesstheDockerremoteAPIforexecutingcommandssuchasstart,stop,build,inspectandsoon.
Dockercommands
WehaveseveralCitrustestactionseachrepresentingaDockercommand.TheseactionscanbepartofatestcasewhereyoucanmanageDockercontainersinsidethetest.AsaprerequisitewehavetoenabletheDockerspecifictestactionsinourXMLtestasfollows:
<beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:docker="http://www.citrusframework.org/schema/docker/testcase"xsi:schemaLocation="
CitrusReferenceGuide
357Docker
![Page 358: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/358.jpg)
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.citrusframework.org/schema/docker/testcasehttp://www.citrusframework.org/schema/docker/testcase/citrus-docker-testcase.xsd">
[...]
</beans>
Weaddedaspecialdockernamespacewithprefixdocker:sonowwecanstarttoaddDockertestactionstothetestcase:
XMLDSL
<testcasename="DockerCommandIT"><actions><docker:ping></docker:ping>
<docker:version><docker:expect><docker:result><![CDATA["Version":"1.8.3","ApiVersion":"1.21","GitCommit":"@ignore@","GoVersion":"go1.4.2","Os":"darwin","Arch":"amd64","KernelVersion":"@ignore@"]]></docker:result></docker:expect></docker:version></actions></testcase>
InthisverysimpleexamplewefirstpingtheDockerdaemontomakesurewehaveconnectivityupandrunning.AfterthatwegettheDockerversioninformation.ThesecondactionshowsanimportantconceptwhenexecutingDockercommandsinCitrus.Asatesterwemightbeinterestedinvalidatingthecommandresult.Sowencanspecifyanoptionaldocker:resultwhichisusuallyinJSONdataformat.AsusualwecanusetestvariableshereandignoresomevaluesexplicitlysuchastheGitCommitvalue.
BasedonthatwecanexecuteseveralDockercommandsinatestcase:
CitrusReferenceGuide
358Docker
![Page 359: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/359.jpg)
XMLDSL
<testcasename="DockerCommandIT"><variables><variablename="imageId"value="busybox"></variable><variablename="containerName"value="citrus_box"></variable></variables>
<actions><docker:pullimage="$imageId"tag="latest"/>
<docker:createimage="$imageId"name="$containerName"cmd="top"><docker:expect><docker:result><![CDATA["Id":"@variable(containerId)@","Warnings":null]]></docker:result></docker:expect></docker:create>
<docker:startcontainer="$containerName"/></actions></testcase>
InthisexamplewepullaDockerimage,buildanewcontaineroutofthisimageandstartthecontainer.AsyoucanseeeachDockercommandactionoffersattributessuchascontainer,imageortag.ThesearecommandsettingsthatareavailableontheDockercommandspecification.ReadmoreabouttheDockercommandsandthespecificsettingsinofficialDockerAPIreferenceguide.
CitrussupportsthefollowingDockercommandswithrespectivetestactions:
docker:pulldocker:builddocker:createdocker:startdocker:stopdocker:waitdocker:pingdocker:versiondocker:inspect
CitrusReferenceGuide
359Docker
![Page 360: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/360.jpg)
docker:removedocker:info
SomeoftheDockercommandscanbeexecutedbothoncontainerandimagetargetssuchasdocker:inspectordocker:remove.Thecommandactionthenoffersbothcontainerandimageattributessotheusercanchoosethetargetofthecommandoperationtobeacontaineroranimage.
UptonowwehaveonlyusedtheCitrusXMLDSL.OfcourseallDockercommandsarealsoavailableinJavaDSLasthenextexampleshows.
JavaDSL
@CitrusTestpublicvoiddockerTest()docker().version().validateCommandResult(newCommandResultCallback<Version>()@OverridepublicvoiddoWithCommandResult(Versionversion,TestContextcontext)Assert.assertEquals(version.getApiVersion(),"1.20"););
docker().ping();
docker().start("my_container");
TheJavaDSLDockercommandsprovideanoptionalCommandResultCallbackthatiscalledwiththeunmarshalledcommandresultobject.IntheexampleabovetheVersionmodelobjectispassedasargumenttothecallback.Sothetestercanaccessthecommandresultandvalidateitspropertieswithassertions.
BydefaultCitrustriestofindaDockerclientcomponentwithintheCitrusSpringapplicationcontext.IfnotpresentCitruswillinstantiateadefaultdockerclientwithalldefaultsettings.YoucanalsoexplicitlysetthedockerclientinstancewhenusingtheJavaDSLDockercommandactions:
JavaDSL
@AutowiredprivateDockerClientdockerClient;
@CitrusTestpublicvoiddockerTest()
CitrusReferenceGuide
360Docker
![Page 361: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/361.jpg)
docker().client(dockerClient).version().validateCommandResult(newCommandResultCallback<Version>()@OverridepublicvoiddoWithCommandResult(Versionversion,TestContextcontext)Assert.assertEquals(version.getApiVersion(),"1.20"););
docker().client(dockerClient).ping();
docker().client(dockerClient).start("my_container");
CitrusReferenceGuide
361Docker
![Page 362: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/362.jpg)
KubernetessupportKubernetesisoneofthehottestmanagementplatformsforcontainerizedapplicationsthesedays.Kubernetesletsyoudeploy,scaleandmanageyourcontainersontheplatformsoyougetfeatureslikeauto-scaling,self-healing,servicediscoveryandloadbalancing.CitrusprovidesinteractionwiththeKubernetesRESTAPIsoyoucanaccesstheKubernetesplatformanditsresourceswithinaCitrustestcase.
NoteTheKubernetestestcomponentsinCitrusarekeptinaseparateMavenmodule.IfnotalreadydonesoyouhavetoincludethemoduleasMavendependencytoyourproject
<dependency><groupId>com.consol.citrus</groupId><artifactId>citrus-kubernetes</artifactId><version>2.7.1</version></dependency>
Citrusprovidesa"citrus-kubernetes"configurationnamespaceandschemadefinitionforKubernetesrelatedcomponentsandactions.IncludethisnamespaceintoyourSpringconfigurationinordertousetheCitrusKubernetesconfigurationelements.ThenamespaceURIandschemalocationareaddedtotheSpringconfigurationXMLfileasfollows.
<beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:citrus-k8s="http://www.citrusframework.org/schema/kubernetes/config"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.citrusframework.org/schema/kubernetes/confighttp://www.citrusframework.org/schema/kubernetes/config/citrus-kubernetes-config.xsd">
[...]
</beans>
AfterthatyouareabletousecustomizedCitrusXMLelementsinordertodefinetheSpringbeans.
CitrusReferenceGuide
362Kubernetes
![Page 363: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/363.jpg)
Kubernetesclient
CitrusoperateswiththeKubernetesremoteRESTAPIinordertointeractwiththeKubernetesplatform.TheKubernetesclientisdefinedasSpringbeancomponentintheconfigurationasfollows:
<citrus-k8s:clientid="myK8sClient"/>
TheKubernetesclientisbasedontheFabric8JavaKubernetesclientimplementation.Followingfromthatthecomponentcanbeconfiguredinvariousways.BydefaulttheclientreadsthesystempropertiesaswellasenvironmentvariablesfordefaultKubernetessettingssuchas:
kubernetes.master/KUBERNETES_MASTERkubernetes.api.version/KUBERNETES_API_VERSIONkubernetes.trust.certificates/KUBERNETES_TRUST_CERTIFICATES
Ifyousetthesepropertiesinyourenvironmenttheclientcomponentwillautomaticallypickuptheconfigurationsettings.Alsowhenusingkubectlcommandlinelocallytheclientmayautomaticallyusethestoreduserauthenticationsettingsfromthere.ForacompletelistofsettingsandexplanationofthosepleaserefertotheFabric8clientdocumentation.
IncaseyouneedtosettheclientconfigurationexplicitlyonyourenvironmentyoucanalsouseexplicitsettingsontheKubernetesclientcomponent:
<citrus-k8s:clientid="myK8sClient"url="http://localhost:8843"version="v1"username="user"password="s!cr!t"namespace="user_namespace"message-converter="messageConverter"object-mapper="objectMapper"/>
NowCitrusisabletoaccesstheKubernetesremoteAPIforexecutingcommandssuchaslist-pods,watch-servicesandsoon.CitrusprovidesasetofactionsthatperformaKubernetescommandviaREST.TheresultsusuallygetvalidatedintheCitrustestasusual.
BasedonthatwecanexecuteseveralKubernetescommandsinatestcaseandvalidatetheJsonresults:
CitrusReferenceGuide
363Kubernetes
![Page 364: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/364.jpg)
CitrussupportsthefollowingKubernetesAPIcommandswithrespectivetestactions:
k8s:infok8s:list-podsk8s:get-podk8s:delete-podk8s:list-servicesk8s:get-servicek8s:delete-servicek8s:list-namespacesk8s:list-eventsk8s:list-endpointsk8s:list-nodesk8s:list-replication-controllersk8s:watch-podsk8s:watch-servicesk8s:watch-namespacesk8s:watch-nodesk8s:watch-replication-controllers
Wewilldiscussthesecommandsindetaillateroninthischapter.FornowletshaveacloserlookonhowtousethecommandsinsideofaCitrustest.
KubernetescommandsinXML
WehaveseveralCitrustestactionseachrepresentingaKubernetescommand.TheseactionscanbepartofatestcasewhereyoucanmanageKubernetespodsinsidethetest.AsaprerequisitewehavetoenabletheKubernetesspecifictestactionsinourXMLtestasfollows:
<beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:k8s="http://www.citrusframework.org/schema/kubernetes/testcase"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.citrusframework.org/schema/kubernetes/testcasehttp://www.citrusframework.org/schema/kubernetes/testcase/citrus-kubernetes-testcase.xsd"
[...]
</beans>
CitrusReferenceGuide
364Kubernetes
![Page 365: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/365.jpg)
Weaddedaspecialkubernetesnamespacewithprefixk8s:sonowwecanstarttoaddKubernetestestactionstothetestcase:
XMLDSL
<testcasename="KubernetesCommandIT"><actions><k8s:infoclient="myK8sClient"><k8s:validate><k8s:result>"result":"clientVersion":"1.4.27","apiVersion":"v1","kind":"Info","masterUrl":"$masterUrl","namespace":"test"</k8s:result></k8s:validate></k8s:info>
<k8s:list-pods><k8s:validate><k8s:result>"result":"apiVersion":"v1","kind":"PodList","metadata":"@ignore@","items":[]</k8s:result><k8s:elementpath="$.result.items.size()"value="0"/></k8s:validate></k8s:list-pods></actions></testcase>
InthisverysimpleexamplewefirstpingtheKubernetesRESTAPItomakesurewehaveconnectivityupandrunning.TheinfocommandconnectstheRESTAPIandreturnsalistofstatusinformationoftheKubernetesclient.AfterthatwegetthelistofavailableKubernetespods.Asatesterwemightbeinterestedinvalidatingthecommandresults.Sowencanspecifyanoptionalk8s:resultwhichisusuallyinJsonformat.WiththatwecanapplythefullCitrusJsonvalidationpowertotheKubernetes
CitrusReferenceGuide
365Kubernetes
![Page 366: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/366.jpg)
results.Asusualwecanusetestvariableshereandignoresomevaluesexplicitlysuchasthemetadatavalue.AlsoJsonPathexpressionvalidationandJsontestmessagevalidationfeaturesinCitruscomeinheretovalidatetheresults.
KubernetescommandsinJava
UptonowwehaveonlyusedtheCitrusXMLDSL.OfcourseallKubernetescommandsarealsoavailableinJavaDSLasthenextexampleshows.
JavaDSL
@CitrusTestpublicvoidkubernetesTest()kubernetes().info().validate(newCommandResultCallback<InfoResult>()@OverridepublicvoiddoWithCommandResult(InfoResultinfo,TestContextcontext)Assert.assertEquals(info.getApiVersion(),"v1"););
kubernetes().pods().list().withoutLabel("running").label("app","myApp");
TheJavaDSLKubernetescommandsprovideanoptionalCommandResultCallbackthatisautomaticallycalledwiththeunmarshalledcommandresultobject.IntheexampleabovetheInfoResultmodelobjectispassedasargumenttothecallback.Sothetestercanaccessthecommandresultandvalidateitspropertieswithassertions.
Java8Lambdaexpressionsaddsomesyntacticalsugartothecommandresultvalidation:
JavaDSL
@CitrusTestpublicvoidkubernetesTest()kubernetes().info().validate((info,context)->Assert.assertEquals(info.getApiVersion(),"v1"));
kubernetes().pods().list()
CitrusReferenceGuide
366Kubernetes
![Page 367: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/367.jpg)
.withoutLabel("running").label("app","myApp");
BydefaultCitrustriestofindaKubernetesclientcomponentwithintheCitrusSpringapplicationcontext.IfnotpresentCitruswillinstantiateadefaultkubernetesclientwithalldefaultsettings.YoucanalsoexplicitlysetthekubernetesclientinstancewhenusingtheJavaDSLKubernetescommandactions:
JavaDSL
@AutowiredprivateKubernetesClientkubernetesClient;
@CitrusTestpublicvoidkubernetesTest()kubernetes().client(kubernetesClient).info().validate((info,context)->Assert.assertEquals(info.getApiVersion(),"v1"));
kubernetes().client(kubernetesClient).pods().list().withoutLabel("running").label("app","myApp");
Infocommand
TheinfocommandjustgetstheclientconnectionsettingsandprovidesthemasaJsonresulttotheaction.
XMLDSL
<k8s:infoclient="myK8sClient"><k8s:validate><k8s:result>"result":"clientVersion":"1.4.27","apiVersion":"v1","kind":"Info","masterUrl":"$masterUrl","namespace":"test"
CitrusReferenceGuide
367Kubernetes
![Page 368: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/368.jpg)
</k8s:result></k8s:validate></k8s:info>
JavaDSL
@CitrusTestpublicvoidinfoTest()kubernetes().info().validate((info,context)->Assert.assertEquals(info.getApiVersion(),"v1"));
Listresources
WecanlistKubernetesresourcessuchaspods,services,endpointsandreplicationcontrollers.Thelistcanbefilteredbyseveralpropertiessuchas
labelnamespace
Thetestactionisabletodefinerespectivefilterstothelistsowegetonlypodsthematchthegivenattributes:
XMLDSL
<k8s:list-podslabel="app=todo"><k8s:validate><k8s:result>"result":"apiVersion":"$apiVersion","kind":"PodList","metadata":"@ignore@","items":"@ignore@"</k8s:result><k8s:elementpath="$.result.items.size()"value="1"/><k8s:elementpath="$..status.phase"value="Running"/></k8s:validate></k8s:list-pods>
JavaDSL
@CitrusTestpublicvoidlistPodsTest()
CitrusReferenceGuide
368Kubernetes
![Page 369: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/369.jpg)
kubernetes().client(k8sClient).pods().list().label("app=todo").validate("$..status.phase","Running").validate((pods,context)->Assert.assertFalse(CollectionUtils.isEmpty(pods.getResult().getItems())););
Asyoucanseeweareabletogivethepodlabelthatissearchedforinlistofallpods.ThelistreturnedisvalidatedeitherbygivinganexpectedJsonmessageorbyaddingJsonPathexpressionswithexpectedvaluestocheck.
InJavaDSLwecanaddavalidationresultcallbackthatisprovidedwiththeunmarshalledresultobjectforvalidation.Besideslabelfilteringwecanalsospecifythenamespaceandthepodnametosearchfor.
Youcanalsodefinemultiplelabelsascommadelimitedlist:
<k8s:list-serviceslabel="stage!=test,provider=fabric8"namespace="default"/>
Asyoucanseewehavecombinedtolabelfiltersstage!=testandprovider=fabric8onpodsinnamespacedefault.Thefirstlabelfilterisnegatedsothelabelstageshouldnotbetesthere.
Listnodesandnamespaces
Nodesandnamespacesarespecialresourcesthatarenotfilteredbytheirnamespaceastheyaremoreglobalresources.Therestisprettysimilartolistingpodsorservices.Wecanaddfilteressuchasnameandlabel.
XMLDSL
<k8s:list-namespaceslabel="provider=citrus"><k8s:validate><k8s:elementpath="$.result.items.size()"value="1"/></k8s:validate></k8s:list-namespaces>
JavaDSL
CitrusReferenceGuide
369Kubernetes
![Page 370: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/370.jpg)
@CitrusTestpublicvoidlistPodsTest()kubernetes().client(k8sClient).namespaces().list().label("provider=citrus").validate((pods,context)->Assert.assertFalse(CollectionUtils.isEmpty(pods.getResult().getItems())););
Getresources
WecangetaveryspecialKubernetesresourcesuchasapodorservicefordetailedvalidationofthatresource.WeneedtospecifyaresourcenameinordertoselecttheresourcefromlistofavailableresourcesinKubernetes.
XMLDSL
<k8s:get-podname="citrus_pod"><k8s:validate><k8s:result>"result":"apiVersion":"$apiVersion","kind":"Pod","metadata":"annotations":"@ignore@","creationTimestamp":"@ignore@","finalizers":[],"generateName":"@startsWith('hello-minikube-')@","labels":"pod-template-hash":"@ignore@","run":"hello-minikube","name":"$podName","namespace":"default","ownerReferences":"@ignore@","resourceVersion":"@ignore@","selfLink":"/api/$apiVersion/namespaces/default/pods/$podName","uid":"@ignore@","spec":"containers":["args":[],"command":[],"env":[],"image":"gcr.io/google_containers/echoserver:1.4",
CitrusReferenceGuide
370Kubernetes
![Page 371: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/371.jpg)
"imagePullPolicy":"IfNotPresent","name":"hello-minikube","ports":["containerPort":8080,"protocol":"TCP"],"resources":,"terminationMessagePath":"/dev/termination-log","volumeMounts":"@ignore@"],"dnsPolicy":"ClusterFirst","imagePullSecrets":"@ignore@","nodeName":"minikube","restartPolicy":"Always","securityContext":"@ignore@","serviceAccount":"default","serviceAccountName":"default","terminationGracePeriodSeconds":30,"volumes":"@ignore@","status":"@ignore@"</k8s:result><k8s:elementpath="$..status.phase"value="Running"/></k8s:validate></k8s:get-pod>
JavaDSL
@CitrusTestpublicvoidgetPodsTest()kubernetes().client(k8sClient).pods().get("citrus_pod").validate("$..status.phase","Running").validate((pod,context)->Assert.assertEquals(pods.getResult().getStatus().getPhase(),"Running"););
AsyoucanseeweareablegetthecompletepodinformationfromKubernetes.TheresultisvalidatedwithJsonmessagevalidatorinCitrus.Thismeanswecanuse@ignore@aswellastestvariablesandJsonPathexpressions.
Createresources
CitrusReferenceGuide
371Kubernetes
![Page 372: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/372.jpg)
WecancreatenewKubernetesresourceswithinaCitrustest.Thisisveryimportantincaseweneedtosetupnewpodsorservicesforthetestrun.Youcancreatenewresourcesbygivinga.ymlfileholdingallinformationhowtocreatethenewresource.SeethefollowingsampleYAMLforanewpodandservice:
kind:PodapiVersion:v1metadata:name:hello-jetty-$randomIdnamespace:defaultselfLink:/api/v1/namespaces/default/pods/hello-jetty-$randomIduid:citrus:randomUUID()labels:server:hello-jettyspec:containers:-name:hello-jettyimage:jetty:9.3imagePullPolicy:IfNotPresentports:-containerPort:8080protocol:TCPrestartPolicy:AlwaysterminationGracePeriodSeconds:30dnsPolicy:ClusterFirstserviceAccountName:defaultserviceAccount:defaultnodeName:minikube
ThisYAMLfilespecifiesanewresourceofkindPod.Wedefinethemetadataaswellasallcontainersthatarepartofthispod.Thecontainerisbuildfromjetty:9.3DockerimagethatshouldbepulledautomaticallyfromDockerHubregistry.Wealsoexposeport8080ascontainerPortsotheupcomingserviceconfigurationcanprovidethisporttoclientsasKubernetesservice.
kind:ServiceapiVersion:v1metadata:name:hello-jettynamespace:defaultselfLink:/api/v1/namespaces/default/services/hello-jettyuid:citrus:randomUUID()labels:service:hello-jettyspec:ports:-protocol:TCP
CitrusReferenceGuide
372Kubernetes
![Page 373: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/373.jpg)
port:8080targetPort:8080nodePort:31citrus:randomNumber(3)selector:server:hello-jettytype:NodePortsessionAffinity:None
Theserviceresourcemapstheport8080andselectsallpodswithlabelserver=hello-jetty.Thismakesthejettycontaineravailabletoclients.TheservicetypeisNodePortwhichmeansthatclientsoutsideofKubernetesarealsoabletoaccesstheservicebyusingthedynamicportnodePort=31xxx.WecanuseCitrusfunctionssuchasrandomNumberintheYAMLfiles.
InthetestcasewecanusetheseYAMLfilestocreatetheresourcesinKubernetes:
XMLDSL
<k8s:create-podnamespace="default"><k8s:templatefile="classpath:templates/hello-jetty-pod.yml"/></k8s:create-pod>
<k8s:create-servicenamespace="default"><k8s:templatefile="classpath:templates/hello-jetty-service.yml"/></k8s:create-service>
JavaDSL
@CitrusTestpublicvoidcreatePodsTest()kubernetes().pods().create(newClassPathResource("templates/hello-jetty-pod.yml")).namespace("default");
kubernetes().services().create(newClassPathResource("templates/hello-jetty-service.yml")).namespace("default");
Creatingnewresourcesmaytakesometimetofinish.Kuberneteswillhavetopullimages,buildcontainersandstartupeverything.Thecreateactionisnotwaitingsynchronouslyforallthattohavehappened.Thereforewemightaddalist-podsactionthatwaitsforthenewresourcestoappear.
CitrusReferenceGuide
373Kubernetes
![Page 374: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/374.jpg)
<repeat-onerror-until-truecondition="@assertThat('greaterThan(9)')@"auto-sleep="1000"><k8s:list-podslabel="server=hello-jetty"><k8s:validate><k8s:elementpath="$.result.items.size()"value="1"/><k8s:elementpath="$..status.phase"value="Running"/></k8s:validate></k8s:list-pods></repeat-onerror-until-true>
Withthisrepeatonerroractionwewaitforthenewserver=hello-jettylabeledpodtobeinstateRunning.
Deleteresources
WiththatcommandweareabletodeletearesourceinKubernetes.Uptonowdeletionofpodsandservicesissupported.Wehavetogiveanameoftheresourcethatwewanttodelete.
XMLDSL
<k8s:delete-podname="citrus_pod"><k8s:validate><k8s:elementpath="$.result.success"value="true"/></k8s:validate></k8s:delete-pod>
JavaDSL
@CitrusTestpublicvoiddeletePodsTest()kubernetes().pods().delete("citrus_pod").validate((result,context)->Assert.assertTrue(result.getResult().getSuccess()));
Watchresources
NoteThewatchoperationisstillinexperimentalstateandmayfacesevereadjustmentsandimprovementsinnearfuture.
CitrusReferenceGuide
374Kubernetes
![Page 375: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/375.jpg)
WhenusingawatchcommandweaddasubscriptiontochangeeventsonaKubernetesresources.Sowecanwatchresourcessuchaspods,servicesforfuturechanges.Eachchangeonthatresourcetriggersanewwatcheventresultthatwecanexpectandvalidate.
XMLDSL
<k8s:watch-podslabel="provider=citrus"><k8s:validate><k8s:elementpath="$.action"value="DELETED"/></k8s:validate></k8s:watch-pods>
JavaDSL
@CitrusTestpublicvoidlistPodsTest()kubernetes().pods().watch().label("provider=citrus").validate((watchEvent,context)->Assert.assertFalse(watchEvent.hasError());Assert.assertEquals(((WatchEventResult)watchEvent).getAction(),Watcher.Action.DELETED););
NoteThewatchcommandmaybetriggeredseveraltimesformultiplechangesontherespectiveKubernetesresource.Thewatchactionwillalwayshandleonesingleeventresult.Thefirsteventtriggerisforwardedtotheactionvalidation.Allfurtherwatcheventsonthatsameresourceareignored.Thismeansthatyoumayneedmultiplewatchactionsinyourtestcaseincaseyouexpectmultiplewatcheventstobetriggered.
Kubernetesmessaging
WehaveseenhowtoaccesstheKubernetesremoteRESTAPIbyusingspecialCitrustestactionsinouttest.Asanalternativetothatwecanalsousemoregenericsend/receiveactionsinCitrusforaccessingtheKubernetesAPI.Wedemonstratethiswithasimpleexample:
XMLDSL
CitrusReferenceGuide
375Kubernetes
![Page 376: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/376.jpg)
<testcasename="KubernetesSendReceiveIT"><actions><sendendpoint="k8sClient"><message><data>"command":"info"</data></message></send>
<receiveendpoint="k8sClient"><messagetype="json"><data>"command":"info","result":"clientVersion":"1.4.27","apiVersion":"v1","kind":"Info","masterUrl":"$masterUrl","namespace":"test"</data></message></receive>
<echo><message>Listallpods</message></echo>
<sendendpoint="k8sClient"><message><data>"command":"list-pods"</data></message></send>
<receiveendpoint="k8sClient"><messagetype="json"><data>"command":"list-pods","result":"apiVersion":"v1","kind":"PodList","metadata":"@ignore@","items":[]</data><validatepath="$.result.items.size()"value="0"/></message></receive>
CitrusReferenceGuide
376Kubernetes
![Page 377: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/377.jpg)
</actions></testcase>
Asyoucanseewecanusethesend/receiveactionstocallKubernetesAPIcommandsandreceivetherespectiveresultsinJsonformat,too.ThisgivesusthewellknownJsonvalidationmechanisminCitrusinordertovalidatetheresultsfromKubernetes.ThiswayyoucanloadKubernetesresourcesverifyingitsstateandproperties.OfcourseJsonPathexpressionsalsocomeinhereinordertovalidateJsonelementsexplicitly.
CitrusReferenceGuide
377Kubernetes
![Page 378: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/378.jpg)
SSHsupportInthespiritofotherCitrusmockservices,thereissupportforsimulatinganexternalSSHserveraswellasforconnectingtoSSHserversasaclientduringthetestexecution.CitrustranslatesSSHrequestsandresponsestosimpleXMLdocumentsforbettervalidationwiththecommonCitrusmechanisms.
ThismeansthattheCitrustestcasedoesnotdealwithpureSSHprotocolcommands.InsteadofthisweusethepowerfulXMLvalidationcapabilitiesinCitruswhendealingwiththesimpleXMLdocumentsthatrepresenttheSSHrequest/responsedata.
Letusclarifythiswithalittleexample.OncetherealSSHserverdaemonisfiredupwithinCitrusweacceptaSSHEXECrequestforinstance.TherequestistranslatedintoaXMLmessageofthefollowingformat:
<ssh-requestxmlns="http://www.citrusframework.org/schema/ssh/message"><command>cat-|sed-e's/Hello/HelloSSH/'</command><stdin>HelloWorld</stdin></ssh-request>
ThismessagecanbevalidatedwiththeusualCitrusmechanisminareceivetestaction.Ifyoudonotknowhowtodothis,pleasereadoneofthesectionsaboutXMLmessagevalidationinthisreferenceguidefirst.NowafterhavingreceivedthisrequestmessagetherespectiveSSHresponseshouldbeprovidedasappropriateanswer.ThisisdonewithamessagesendingactiononareplyhandlerasitisknownfromsynchronoushttpmessagecommunicationinCitrusforinstance.TheSSHXMLrepresentationofaresponsemessagelookslikethis:
<ssh-responsexmlns="http://www.citrusframework.org/schema/ssh/message"><stdout>HelloSSHWorld</stdout><stderr></stderr><exit>0</exit></ssh-response>
BesidessimulatingafullfeaturedSSHserver,CitrusalsoprovidesSSHclientfunctionality.Thisclientusesthesamerequestmessagepattern,whichistranslatedintoarealSSHcalltoanSSHserver.TheSSHresponsereceivedisalsotranslatedintoaXMLmessageasshownabovesowecanvalidateitwithknownvalidationmechanismsinCitrus.
CitrusReferenceGuide
378Ssh
![Page 379: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/379.jpg)
SimilartotheotherCitrusmodules(http,soap),aCitrusSSHserverandclientisconfiguredinCitrusSpringapplicationcontext.ThereisadedicatedsshnamespaceavailableforallsshCitruscomponents.Thenamespacedeclarationgoesintothecontexttop-levelelementasusual:
<beans[...]xmlns:citrus-ssh="http://www.citrusframework.org/schema/ssh/config"[...]xsi:schemaLocation="[...]http://www.citrusframework.org/schema/ssh/confighttp://www.citrusframework.org/schema/ssh/config/citrus-ssh-config.xsd[...]">[...]</beans>
Both,SSHserverandclientalongwiththeirconfigurationoptionsaredescribedinthefollowingtwosections.
SSHClient
ACitrusSSHclientisusefulfortestingagainstarealSSHserver.SoCitrusisabletoinvokeSSHcommandsontheexternalserverandvalidatetheSSHresponseaccordingly.ThetestcasedoesnotdealwiththepureSSHprotocolwithinthiscommunication.TheCitrusSSHclientcomponentexpectsacustomizedXMLrepresentationandautomaticallytranslatestheserequestmessagesintoarealSSHcalltoaspecifichost.OncethesynchronousSSHresponsewasreceivedtheresultgetstranslatedbacktotheXMLresponsemessagerepresentation.OnthistranslatedresponsewecaneasilyapplythevalidationstepsbytheusualCitrusmeans.
TheSSHclientcomponentsreceiveitsconfigurationintheSpringapplicationcontextasusual.WecanusethespecialSSHmodulenamespaceforeasyconfiguration:
<citrus-ssh:clientid="sshClient"port="9072"user="roland"private-key-path="classpath:com/consol/citrus/ssh/test_user.priv"strict-host-checking="false"host="localhost"/>
TheSSHclientreceivesseveralattributes,theseare:
CitrusReferenceGuide
379Ssh
![Page 380: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/380.jpg)
id:Ididentifyingthebeanandusedasreferencefromwithtestdescriptions.(e.g.id="sshClient")host:HosttoconnecttoforsendinganSSHExecrequest.Defaultis'localhost'(e.g.host="localhost")portPorttouse.Defaultis2222(e.g.port="9072")private-key-path:Pathtoaprivatekey,whichcanbeeitheraplainfilepathoranclassresourceifprefixedwith'classpath'(e.g.private-key-path="classpath:test_user.priv")private-key-password:Optionalpasswordfortheprivatekey(e.g.password="s!cr!t")user:UserusedforconnectingtotheSSHserver(e.g.user="roland")password:Passwordusedforpasswordbasedauthentication.Mightbecombinedwith"private-key-path"inwhichcasebothauthenticationmechanismaretried(e.g.password="ps!st)strict-host-checking:Whetherthehostkeyshouldbeverifiedbylookingitupina'known_hosts'file.Defaultisfalse(e.g.strict-host-checking="true")known-hosts-path:Pathtoaknownhostsfile.Ifprefixedwith'classpath:'thisfileislookedupasaresourceintheclasspath(e.g.known-hosts-path="/etc/ssh/known_hosts")command-timeout:TimeoutinmillisecondsforhowlongtowaitfortheSSHcommandtocomplete.Defaultis5minutes(e.g.command-timeout="300000")connection-timeout:Timeoutinmillisecondsforhowlongtoforaconnectiuontoconnect.Defaultis1minute(e.g.connection-timeout="60000")actor:Actorusedforswitchinggroupsofactions(e.g.actor="ssh-mock")
OncedefinesasclientcomponentintheSpringapplicationcontexttestcasescanreferencetheclientineverysendtestaction.
<sendendpoint="sshClient"><message><payload><ssh-requestxmlns="http://www.citrusframework.org/schema/ssh/message"><command>shutdown</command><stdin>input</stdin></ssh-request></payload></message></send>
<receiveendpoint="sshClient"><message><payload>
CitrusReferenceGuide
380Ssh
![Page 381: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/381.jpg)
<ssh-responsexmlns="http://www.citrusframework.org/schema/ssh/message"><stdout>HelloCitrus</stdout><stderr/><exit>0</exit></ssh-response></payload></message></receive>
Asyoucanseeweuseusualsendandreceivetestactions.TheXMLSSHrepresentationhelpsustospecifytherequestandresponsedataforvalidation.ThiswayyoucancallSSHcommandsagainstanexternalSSHserverandvalidatetheresponsedata.
SSHServer
NowthatwehaveusedCitrusontheclientsidewecanalsouseCitrusSSHservermoduleinordertoprovideafullstackedSSHserverdaemon.WecanacceptSSHclientconnectionsandprovideproperresponsemessagesasananswer.
GiventheaboveSSHmodulenamespacedeclaration,addinganewSSHserverisquitesimple:
<citrus-ssh:serverid="sshServer"allowed-key-path="classpath:com/consol/citrus/ssh/test_user_pub.pem"user="roland"port="9072"auto-start="true"endpoint-adapter="sshEndpointAdapter"/>
endpoint-adapteristhehandlerwhichreceivestheSSHrequestasmessages(intherequestformatdescribedabove).Endpointadapterimplementationsarefullydescribedinhttp-serverAlladaptersdescribedtherearesupportedinSSHservermodule,too.
The<citrus-ssh:server>supportsthefollowingattributes:
SSHServerAttributes:
id:NameoftheSSHserverwhichidentifiesituniquewithintheCitrusSpringcontext(e.g.id="sshServer")host-key-path:PathtoPEMencodedkeypair(publicandprivatekey)whichisusedashostkey.Bydefault,astandard,pre-generate,fixedkeypairisused.Thepathcanbespecifiedeitherasanfilepath,or,ifprefixedwithclasspath:islooked
CitrusReferenceGuide
381Ssh
![Page 382: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/382.jpg)
upfromwithintheclasspath.Thepaththeisrelativefromtothetop-levelpackage,sonoleadingslashshouldbeused(e.g.hist-key-path="/etc/citrus_ssh_server.pem)user:Userwhichisallowedtoconnect(e.g.user="roland")allowed-key-path:PathtoaSSHpublickeystoredinPEMformat.Thesearethekeys,whichareallowedtoconnecttotheSSHserverwhenpublickeyauthenticationisused.Itsevesthesamepurposeasauthorized_keysforstandardSSHinstallations.Thepathcanbespecifiedeitherasanfilepath,or,ifprefixedwithclasspath:islookedupfromwithintheclasspath.Thepaththeisrelativefromtothetop-levelpackage,sonoleadingslashshouldbeused(e.g.allowed-key-path="classpath:test_user_pub.pem)password:Passwordwhichshouldbeusedwhenpasswordauthenticationisused.Bothpublickeyauthenticationandpasswordbasedauthenticationcanbeusedtogetherinwhichcasebothmethodsaretriedinturn(e.g.password="s!cr!t")host:Hostaddress(e.g.localhost)port:Portonwhichtolisten.TheSSHserverwillbindonlocalhosttothisport(e.g.port="9072")auto-start:WhethertostartthisSSHserverautomatically.Defaultistrue.Ifsettofalse,atestactionisresponsibleforstarting/stoppingtheserver(e.g.auto-start="true")endpoint-adapter:BeanreferencetoaendpointadapterwhichprocessestheincomingSSHrequest.Themessageformatfortherequestandresponsearedescribedabove(e.g.endpoint-adapter="sshEndpointAdapter")
OncetheSSHservercomponentisaddedtotheSpringapplicationcontextwithaproperendpointadapterliketheMessageChannelforwardingadapterwecanreceiveincomingrequestsinatestcaseandprovidearesponemessagefortheclient.
<receiveendpoint="sshServer"><message><payload><ssh-requestxmlns="http://www.citrusframework.org/schema/ssh/message"><command>shutdown</command><stdin>input</stdin></ssh-request></payload></message></receive>
<sendendpoint="sshServer"><message><payload><ssh-responsexmlns="http://www.citrusframework.org/schema/ssh/message"><stdout>HelloCitrus</stdout>
CitrusReferenceGuide
382Ssh
![Page 383: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/383.jpg)
<exit>0</exit></ssh-response></payload></message></send>
CitrusReferenceGuide
383Ssh
![Page 384: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/384.jpg)
RMIsupportRMIstandsforRemoteMethodInvocationandisastandardwayofcallingJavamethodinterfaceswherecallerandcallee(clientandserver)arenotlocatedwithinthesameJVM.Sotheobjectpassedtothemethodasargumentaswellasthemethodreturnvaluearetransmittedoverthewire.
AsaclientCitrusisabletoconnecttosomeRMIregistrythatexposessomeremoteinterfaces.AsaserverCitrusimplementssuchaRMIregistryandhandlesincomingmethodcallswithprovidingtherespectivereturnvalue.
NoteTheRMIcomponentsinCitrusarekeptinaseparateMavenmodule.SoyoushouldcheckthatthemoduleisavailableasMavendependencyinyourproject
<dependency><groupId>com.consol.citrus</groupId><artifactId>citrus-rmi</artifactId><version>2.7.1</version></dependency>
AsusualCitrusprovidesacustomizedrmiconfigurationschemathatisusedinSpringconfigurationfiles.Simplyincludethecitrus-rminamespaceintheconfigurationXMLfilesasfollows.
<beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:citrus="http://www.citrusframework.org/schema/config"xmlns:citrus-rmi="http://www.citrusframework.org/schema/rmi/config"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.citrusframework.org/schema/confighttp://www.citrusframework.org/schema/config/citrus-config.xsdhttp://www.citrusframework.org/schema/rmi/confighttp://www.citrusframework.org/schema/rmi/config/citrus-rmi-config.xsd">
[...]
</beans>
NowyouarereadytousethecustomizedHttpconfigurationelementswiththecitrus-rminamespaceprefix.
CitrusReferenceGuide
384Rmi
![Page 385: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/385.jpg)
ReadthenextsectioninordertofindoutmoreabouttheRMImessagesupportinCitrus.
RMIclient
Ontheclientsidewewanttocalleremoteinterface.Weneedtospecifythemethodtocallaswellasallmethodarguments.Therespectivemethodreturnvalueisreceivablewithinthetestcaseforvalidation.CitrusprovidesaclientcomponentforRMIthatsendsoutserviceinvocationcalls.
<citrus-rmi:clientid="rmiClient1"host="localhost"port="1099"binding="newsService"/>
<citrus-rmi:clientid="rmiClient2"server-url="rmi://localhost:1099/newsService"/>
TheclientcomponentintheSpringapplicationcontextreceiveshostandportconfigurationofavalidRMIserviceregistry.Eitherbyspecifyingaproperserverurlorbygivinghost,portandbindingproperties.Theservicebindingisthenameoftheservicethatwewouldliketoaddressintheregistry.Nowwearereadytousethisclientreferencedbyitsidornameinatestcaseforamessagesendingaction.
XMLDSL
<sendendpoint="rmiClient"><message><payload><service-invocationxmlns="http://www.citrusframework.org/schema/rmi/message"><remote>com.consol.citrus.rmi.remote.NewsService</remote><method>getNews</method></service-invocation></payload></message></send>
JavaDSL
@CitrusTestpublicvoidrmiClientTest()send(rmiClient).message(RmiMessage.invocation(NewsService.class,"getNews"));
CitrusReferenceGuide
385Rmi
![Page 386: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/386.jpg)
WeareusingtheusualCitrussendmessageactionreferencingthermiClientasendpoint.ThemessagepayloadisaspecialCitrusmessagethatdefinestheserviceinvocation.Wedefinetheremoteinterfaceaswellasthemethodtocall.CitrusRMIclientcomponentwillbeabletointerpretthismessagecontentandcalltheservicemethod.
Themethodreturnvalueisreceivableforvalidationusingtheverysameclientendpoint.
XMLDSL
<receiveendpoint="rmiClient"><message><payload><service-resultxmlns="http://www.citrusframework.org/schema/rmi/message"><objecttype="java.lang.String"value="ThisisnewsfromRMI!"/></service-result></payload></message></receive>
JavaDSL
@CitrusTestpublicvoidrmiClientTest()receive(rmiClient).message(RmiMessage.result("ThisisnewsfromRMI!"));
Inthesampleabovewereceivetheserviceresultandexpectajava.lang.Stringobjectreturnvalue.Thereturnvaluecontentisalsovalidatedwithintheserviceresultpayload.
Ofcoursewecanalsodealwithmethodarguments.
XMLDSL
<sendendpoint="rmiClient"><message><payload><service-invocationxmlns="http://www.citrusframework.org/schema/rmi/message"><remote>com.consol.citrus.rmi.remote.NewsService</remote><method>setNews</method><args><argvalue="Thisisbreakingnews!"/></args>
CitrusReferenceGuide
386Rmi
![Page 387: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/387.jpg)
</service-invocation></payload></message></send>
@CitrusTestpublicvoidrmiServerTest()send(rmiClient).message(RmiMessage.invocation(NewsService.class,"setNews").argument("Thisisbreakingnews!"));
Thiscompletesthebasicremoteservicecall.Citrusinvokestheremoteinterfacemethodandvalidatesthemethodreturnvalue.Asatesteryoumightalsofaceerrorsandexceptionswhencallingtheremoteinterfacemethod.Youcancatchandasserttheseremoteexceptionsverifyingyourerrorscenario.
XMLDSL
<assertexception="java.rmi.RemoteException"><when><sendendpoint="rmiClient"><message><payload><service-invocationxmlns="http://www.citrusframework.org/schema/rmi/message"[...]</service-invocation></payload></message></send></when><assert/>
WeasserttheRemoteExceptiontobethrownwhilecallingtheremoteservicemethod.Thisishowyoucanhandlesomesortoferrorsituationwhilecallingremoteservices.InthenextsectionwewillhandleRMIcommunicationwhereCitrusprovidestheremoteinterfaces.
RMIserver
CitrusReferenceGuide
387Rmi
![Page 388: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/388.jpg)
OntheserversideCitrusneedstoprovideremoteinterfaceswithmethodscallableforclients.ThismeansthatCitrusneedstosupportallyourremoteinterfaceswithmethodargumentsandreturnvalues.TheCitrusRMIserverisabletobindyourremoteinterfacestoaserviceregistry.AllincomingRMIclientmethodcallsareautomaticallyacceptedandthemethodargumentsareconvertedintoaCitrusXMLserviceinvocationrepresentation.TheRMImethodcallisthenpassedtotherunningtestforvalidation.
LetushavealookattheCitrusRMIservercomponentandhowyoucanaddittotheSpringapplicationcontext.
<citrus-rmi:serverid="rmiServer"host="localhost"port="1099"interface="com.consol.citrus.rmi.remote.NewsService"binding="newService"create-registry="true"auto-start="true"/>
TheRMIservercomponentusespropertiessuchashostandporttodefinetheserviceregistry.BydefaultCitruswillconnecttothisserviceregistryandbinditsremoteinterfacestoit.Withtheattributecreate-registryCitruscanalsocreatetheregistryforyou.
YouhavetogiveCitrusthefullyqualifiedremoteinterfacenamesoCitruscanbindittotheserviceregistryandhandleincomingmethodcallsproperly.Inyourtestcaseyoucanthenreceivetheincomingmethodcallsontheserverinordertoperformvalidationsteps.
XMLDSL
<receiveendpoint="rmiServer"><message><payload><service-invocationxmlns="http://www.citrusframework.org/schema/rmi/message"><remote>com.consol.citrus.rmi.remote.NewsService</remote><method>getNews</method></service-invocation></payload><header><elementname="citrus_rmi_interface"value="com.consol.citrus.rmi.remote.NewsService"<elementname="citrus_rmi_method"value="getNews"/></header></message></receive>
CitrusReferenceGuide
388Rmi
![Page 389: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/389.jpg)
JavaDSL
@CitrusTestpublicvoidrmiServerTest()receive(rmiServer).message(RmiMessage.invocation(NewsService.class,"getNews"));
AsyoucanseeCitrusconvertstheincomingserviceinvocationtoaspecialXMLrepresentationwhichispassedasmessagepayloadtothetest.AsthisisplainXMLyoucanverifytheRMImessagecontentasusualusingCitrusvariables,functionsandvalidationmatchers.
Sincewehavereceivedthemethodcallweneedtoprovidesomereturnvaluefortheclient.AsusualwecanspecifythemethodreturnvaluewithsomeXMLrepresentation.
XMLDSL
<sendendpoint="rmiServer"><message><payload><service-resultxmlns="http://www.citrusframework.org/schema/rmi/message"><objecttype="java.lang.String"value="ThisisnewsfromRMI!"/></service-result></payload></message></send>
JavaDSL
@CitrusTestpublicvoidrmiServerTest()send(rmiServer).message(RmiMessage.result("ThisisnewsfromRMI!"));
Theserviceresultisdefinedasobjectwithatypeandvalue.TheCitrusRMIremoteinterfacemethodwillreturnthisvaluetothecallingclient.Thiswouldcompletethesuccessfulremoteserviceinvocation.Atthispointwealsohavetothinkofchoosingtoraisesomeremoteexceptionasserviceoutcome.
XMLDSL
CitrusReferenceGuide
389Rmi
![Page 390: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/390.jpg)
<sendendpoint="rmiServer"><message><payload><service-resultxmlns="http://www.citrusframework.org/schema/rmi/message"><exception>Somethingwentwrong<exception/></service-result></payload></message></send>
JavaDSL
@CitrusTestpublicvoidrmiServerTest()send(rmiServer).message(RmiMessage.exception("Somethingwentwrong"));
IntheexampleaboveCitruswillnotreturnsomeobjectasserviceresultbutraiseajava.rmi.RemoteExceptionwithrespectiveerrormessageasspecifiedinthetestcase.Thecallingclientwillreceivetheexceptionaccordingly.
CitrusReferenceGuide
390Rmi
![Page 391: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/391.jpg)
JMXsupportJMXisastandardJavaAPIformakingbeansaccessibletoothersintermsofmanagementandremoteconfiguration.JMXistheshorttermforJavaManagementExtensionsandisoftenusedinJEEapplicationserverstomanagebeanattributesandoperationsfromoutside(e.g.anotherJVM).AmanagedbeanserverhostsmultiplemanagedbeansforJMXaccess.RemoteconnectionstoJMXcanberealizedwithRMI(Remotemethodinvocation)capabilities.
CitrusisabletoconnecttoJMXmanagedbeansasclientandserver.AsaclientCitruscaninvokemanagedbeanoperationsandreadwritemanagedbeanattributes.AsaserverCitrusisabletoexposemanagedbeansasmbeanserver.ClientscanaccessthoseCitrusmanagedbeansandgetproperresponseobjectsasresult.DoingsoyoucanusetheJVMplatformmanagedbeanserverorsomeRMIregistryforprovidingremoteaccess.
NoteTheJMXcomponentsinCitrusarekeptinaseparateMavenmodule.SoyoushouldcheckthatthemoduleisavailableasMavendependencyinyourproject
<dependency><groupId>com.consol.citrus</groupId><artifactId>citrus-jmx</artifactId><version>2.7.1</version></dependency>
AsusualCitrusprovidesacustomizedjmxconfigurationschemathatisusedinSpringconfigurationfiles.Simplyincludethecitrus-jmxnamespaceintheconfigurationXMLfilesasfollows.
<beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:citrus="http://www.citrusframework.org/schema/config"xmlns:citrus-jmx="http://www.citrusframework.org/schema/jmx/config"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.citrusframework.org/schema/confighttp://www.citrusframework.org/schema/config/citrus-config.xsdhttp://www.citrusframework.org/schema/jmx/confighttp://www.citrusframework.org/schema/jmx/config/citrus-jmx-config.xsd">
[...]
CitrusReferenceGuide
391Jmx
![Page 392: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/392.jpg)
</beans>
NowyouarereadytousethecustomizedHttpconfigurationelementswiththecitrus-jmxnamespaceprefix.
NextsectionsdescribetheJMXmessagesupportinCitrusinmoredetail.
JMXclient
Ontheclientsidewewanttocallsomemanagedbeanbyeitheraccessingmanagedattributeswithread/writeorbyinvokingamanagedbeanoperation.ForpropermbeanserverconnectivityweshouldspecifyaclientcomponentforJMXthatsendsoutmbeaninvocationcalls.
<citrus-jmx:clientid="jmxClient"server-url="platform"/>
Theclientcomponentspecifiesthetargetmanagedbeanserverthatwewanttoconnectto.InthisexampleweareusingtheJVMplatformmbeanserver.ThismeansweareabletoaccessallJVMmanagedbeanssuchasMemory,ThreadingandLogging.Inadditiontothatwecanaccessallcustommanagedbeansthatwereexposedtotheplatformmbeanserver.
InmostcasesyoumaywanttoaccessmanagedbeansonadifferentJVMorapplicationserver.Soweneedsomeremoteconnectiontotheforeignmbeanserver.
<citrus-jmx:clientid="jmxClient"server-url="service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi"username="user"password="s!cr!t"auto-reconnect="true"delay-on-reconnect="5000"/>
InthisexampleaboveweconnecttoaremotembeanserverviaRMIusingthedefaultRMIregistrylocalhost:1099andtheservicenamejmxrmi.Citrusisabletohandledifferentremotetransportprotocols.Justdefinethoseintheserver-url.
Nowthatwehavesetuptheclientcomponentwecanuseitinatestcasetoaccessamanagedbean.
XMLDSL
CitrusReferenceGuide
392Jmx
![Page 393: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/393.jpg)
<sendendpoint="jmxClient"><message><payload><mbean-invocationxmlns="http://www.citrusframework.org/schema/jmx/message"><mbean>java.lang:type=Memory</mbean><attributename="Verbose"/></mbean-invocation></payload></message></send>
JavaDSL
@CitrusTestpublicvoidjmxClientTest()send(jmxClient).message(JmxMessage.invocation("java.lang:type=Memory").attribute("Verbose"));
Asyoucanseewejustusedanormalsendactionreferencingthejmxclientcomponentthatwehavejustadded.ThemessagepayloadisaXMLrepresentationofthemanagedbeanaccess.ThisisaspecialCitrusXMLrepresentation.CitruswillconvertthisXMLpayloadtotheactuelmanagedbeanaccess.Intheexampleabovewetrytoaccessamanagedbeanwithobjectnamejava.lang:type=Memory.TheobjectnameisdefinedinJMXspecificationandconsistsofakeyjava.lang:typeandavalueMemory.Soweidentifythemanagedbeanontheserverbyitstype.
NowthatwehaveaccesstothemanagedbeanwecanreaditsmanagedattributessuchasVerbose.ThisisabooleantypeattributesothembeaninvocationresultwillbearespectiveBooleanobject.Wecanvalidatethemanagedbeanattributeaccessinareceiveaction.
XMLDSL
<receiveendpoint="jmxClient"><message><payload><mbean-resultxmlns="http://www.citrusframework.org/schema/jmx/message"><objecttype="java.lang.Boolean"value="false"/></mbean-result></payload></message></receive>
CitrusReferenceGuide
393Jmx
![Page 394: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/394.jpg)
JavaDSL
@CitrusTestpublicvoidjmxClientTest()receive(jmxClient).message(JmxMessage.result(false));
Inthesampleabovewereceivethembeanresultandexpectajava.lang.Booleanobjectreturnvalue.Thereturnvaluecontentisalsovalidatedwithinthembeanresultpayload.
Somemanagedbeanattributesmightalsobesettableforus.Sowencandefinetheattributeaccessaswriteoperationbyspecifyingavalueinthesendactionpayload.
XMLDSL
<sendendpoint="jmxClient"><message><payload><mbean-invocationxmlns="http://www.citrusframework.org/schema/jmx/message"><mbean>java.lang:type=Memory</mbean><attributename="Verbose"value="true"type="java.lang.Boolean"/></mbean-invocation></payload></message></send>
JavaDSL
@CitrusTestpublicvoidjmxClientTest()send(jmxClient).message(JmxMessage.invocation("java.lang:type=Memory").attribute("Verbose",true));
NowwehavewriteaccesstothemanagedattributeVerbose.Wedospecifythevalueanditstypejava.lang.Boolean.Thisishowwecansetattributevaluesonmanagedbeans.
Lastnotleastweareabletoaccessmanagedbeanoperations.
XMLDSL
CitrusReferenceGuide
394Jmx
![Page 395: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/395.jpg)
<sendendpoint="jmxClient"><message><payload><mbean-invocationxmlns="http://www.citrusframework.org/schema/jmx/message"><mbean>com.consol.citrus.jmx.mbean:type=HelloBean</mbean><operationname="sayHello">>parameter>>paramtype="java.lang.String"value="HelloJMX!"/>>/parameter>>/operation></mbean-invocation></payload></message></send>
JavaDSL
@CitrusTestpublicvoidjmxClientTest()send(jmxClient).message(JmxMessage.invocation("com.consol.citrus.jmx.mbean:type=HelloBean").operation("sayHello").parameter("HelloJMX!"));
IntheexampleaboveweaccessacustommanagedbeanandinvokeitsoperationsayHello.Wearealsousingoperationparametersfortheinvocation.Thisshouldcallthemanagedbeanoperationandreturnitsresultifanyasusual.
ThiscompletesthebasicJMXmanagedbeanaccessasclient.NowwealsowanttodiscusstheserversidewereCitrusisabletoprovidemanagedbeansforothers
JMXserver
Theserversideisalwaysalittlebitmoretrickybecauseweneedtosimulatecustommanagedbeanaccessasaserver.FirstofallCitrusprovidesaservercomponentthatspecifiestheconnectionpropertiesforclientssuchastransportprotocols,portsandmbeanobjectnames.LetscreateanewserverthatacceptsincomingrequestsviaRMIonaremoteregistrylocalhost:1099.
<citrus-jmx:serverid="jmxServer"server-url="service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi"<citrus-jmx:mbeans><citrus-jmx:mbeantype="com.consol.citrus.jmx.mbean.HelloBean"/><citrus-jmx:mbeantype="com.consol.citrus.jmx.mbean.NewsBean"objectDomain="com.consol.citrus.news"objectName="name=News"/>
CitrusReferenceGuide
395Jmx
![Page 396: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/396.jpg)
</citrus-jmx:mbeans></citrus-jmx:server>
Asusualwedefineaserver-urlthatcontrolstheJMXconnectoraccesstothembeanserver.InthisexampleaboveweopenaJMXRMIconnectorforclientsusingtheregistrylocalhost:1099andtheservicenamejmxrmiBydefaultCitruswillnotattempttocreatethisregistryautomaticallysotheregistryhastobepresentbeforetheserverstartup.Withtheoptionalserverpropertycreate-registrysettotrueyoucanautocreatetheregistrywhentheserverstartsup.ThesepropertiesdoonlyapplywhenusingaremoteJMXconnectorserver.
Besidesusingthewholeserver-urlaspropertywecanalsoconstructtheconnectionbyhost,port,protocolandbindingproperties.
<citrus-jmx:serverid="jmxServer"host="localhost"port="1099"protocol="rmi"binding="jmxrmi"<citrus-jmx:mbeans><citrus-jmx:mbeantype="com.consol.citrus.jmx.mbean.HelloBean"/><citrus-jmx:mbeantype="com.consol.citrus.jmx.mbean.NewsBean"objectDomain="com.consol.citrus.news"objectName="name=News"/></citrus-jmx:mbeans></citrus-jmx:server>
Onlastthingtomentionisthatwecouldhavealsousedplatformasserver-urlinordertousetheJVMplatformmbeanserverinstead.
NowthatweclarifiedtheconnectivityweneedtotalkabouthowtodefinethemanagedbeansthatareavailableonourJMXmbeanserver.Thisisdoneasnestedmbeanconfigurationelements.HerethemanagedbeandefinitionsdescribethemanagedbeanwithitsobjectDomain,objectName,operationsandattributes.Themostconvenientwayofdefiningsuchmanagedbeandefinitionsistogiveabeantypewhichisthefullyqualifiedclassnameofthemanagedbean.CitruswillusethepackagenameandclassnameforproperobjectDomainandobjectNameconstruction.
Letshaveacloserlookattheirstmbeandefinitionintheexampleabove.Sothefirstmanagedbeanisdefinedbyitsclassnamecom.consol.citrus.jmx.mbean.HelloBeanandthereforeisaccessibleusingtheobjectNamecom.consol.citrus.jmx.mbean:type=HelloBean.InadditiontothatCitruswillreadthe
CitrusReferenceGuide
396Jmx
![Page 397: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/397.jpg)
classinformationsuchasavailablemethods,gettersandsettersforconstructingaproperMBeanInfo.InthesecondmanagedbeandefinitioninourexamplewehaveusedadditionalcustomobjectDomainandobjectNamevalues.SotheNewsBeanwillbeaccessiblewithcom.consol.citrus.news:name=Newsonthemanagedbeanserver.
Thisishowwecandefinethebindingsofmanagedbeansandwhatclientsneedtosearchforwhenfindingandaccessingthemanagedbeansontheserver.WhenclientstrytofindthemanagedbeanstheyhavetouseproperobjectNamesaccordingly.ObjectNamesthatarenotdefinedontheserverwillberejectedwithmanagedbeannotfounderror.
Rightnowwehavetousethequalifiedclassnameofthemanagedbeaninthedefinition.Whathappensifwedonothaveaccesstothatmbeanclassorifthereisnotmanagedbeaninterfaceavailableatall?Citrusprovidesagenericmanagedbeanthatisabletohandleanymanagedbeaninteraction.Thegenericbeanimplementationneedstoknowthemanagedoperationsandattributesthough.Soletsdefineanewgenericmanagedbeanonourserver:
<citrus-jmx:serverid="jmxServer"server-url="service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi"<citrus-jmx:mbeans><citrus-jmx:mbeanname="fooBean"objectDomain="foo.object.domain"objectName="type=FooBean"><citrus-jmx:operations><citrus-jmx:operationname="fooOperation"><citrus-jmx:parameter><citrus-jmx:paramtype="java.lang.String"/><citrus-jmx:paramtype="java.lang.Integer"/></citrus-jmx:parameter></citrus-jmx:operation><citrus-jmx:operationname="barOperation"/></citrus-jmx:operations><citrus-jmx:attributes><citrus-jmx:attributename="fooAttribute"type="java.lang.String"/><citrus-jmx:attributename="barAttribute"type="java.lang.Boolean"/></citrus-jmx:attributes></citrus-jmx:mbean></citrus-jmx:mbeans></citrus-jmx:server>
Thegenericbeandefinitionneedstodefinealloperationsandattributesthatareavailableforaccess.UptonowwearerestrictedtousingJavabasetypeswhendefiningoperationparameterandattributereturntypes.Thereisactuallynowaytodefinemore
CitrusReferenceGuide
397Jmx
![Page 398: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/398.jpg)
complexreturntypes.NeverthelessCitrusisnowabletoexposethemanagedbeanforclientaccesswithouthavingtoknowtheactualmanagedbeanimplementation.
Nowwecanusetheservercomponentinatestcasetoreceivesomeincomingmanagedbeanaccess.
XMLDSL
<receiveendpoint="jmxServer"><message><payload><mbean-invocationxmlns="http://www.citrusframework.org/schema/jmx/message"><mbean>com.consol.citrus.jmx.mbean:type=HelloBean</mbean><operationname="sayHello">>parameter>>paramtype="java.lang.String"value="HelloJMX!"/>>/parameter></operation></mbean-invocation></payload></message></receive>
JavaDSL
@CitrusTestpublicvoidjmxServerTest()receive(jmxServer).message(JmxMessage.invocation("com.consol.citrus.jmx.mbean:type=HelloBean").operation("sayHello").parameter("HelloJMX!"));
Inthisveryfirstexampleweexpectamanagedbeanaccesstothebeancom.consol.citrus.jmx.mbean:type=HelloBean.WefurtherexpecttheoperationsayHellotobecalledwithrespectiveparametervalues.Nowwehavetodefinetheoperationresultthatwillbereturnedtothecallingclientasoperationresult.
XMLDSL
<sendendpoint="jmxServer"><message><payload><mbean-resultxmlns="http://www.citrusframework.org/schema/jmx/message"><objecttype="java.lang.String"value="HellofromJMX!"/></mbean-result>
CitrusReferenceGuide
398Jmx
![Page 399: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/399.jpg)
</payload></message></send>
JavaDSL
@CitrusTestpublicvoidjmxServerTest()send(jmxServer).message(JmxMessage.result("HellofromJMX!"));
TheoperationreturnsaStringHellofromJMX!.Thisishowwecanexpectoperationcallsonmanagedbeans.Nowwealreadyhaveseenthatmanagedbeansalsoexposeattributes.Thenextexampleishandlingincomingattributereadaccess.
XMLDSL
<receiveendpoint="jmxServer"><message><payload><mbean-invocationxmlns="http://www.citrusframework.org/schema/jmx/message"><mbean>com.consol.citrus.news:name=News</mbean>>attributename="newsCount"/></mbean-invocation></payload></message></receive>
<sendendpoint="jmxServer"><message><payload><mbean-resultxmlns="http://www.citrusframework.org/schema/jmx/message"><objecttype="java.lang.Integer"value="100"/></mbean-result></payload></message></send>
JavaDSL
@CitrusTestpublicvoidjmxServerTest()receive(jmxServer).message(JmxMessage.invocation("com.consol.citrus.news:name=News").attribute("newsCount");
CitrusReferenceGuide
399Jmx
![Page 400: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/400.jpg)
send(jmxServer).message(JmxMessage.result(100));
ThereceiveactionexpectsreadaccesstotheNewsBeanattributenewsCountandreturnsaresultobjectoftypejava.lang.Integer.Thiswaywecanexpectallattributeaccesstoourmanagedbeans.Writeoperationswillhaveaattributevaluespecified.
ThiscompletestheJMXservercapabilitieswithmanagedbeanaccessonoperationsandattributes.
CitrusReferenceGuide
400Jmx
![Page 401: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/401.jpg)
CucumberBDDsupportBehaviordrivendevelopment(BDD)isbecomingmoreandmorepopularthesedays.Theideaofdefininganddescribingthesoftwarebehaviorasbasisforalltestsinpriortotranslatingthosefeaturedescriptionsintoexecutabletestsisaveryinterestingapproachbecauseitincludesthetechnicalexpertsaswellasthedomainexperts.WithBDDthedomainexpertscaneasilyreadandverifythetestsandthetechnicalexpertsgetadetaileddescriptionofwhatshouldhappeninthetest.
ThetestscenariodescriptionsfollowtheGherkinsyntaxwitha"Given-When-Then"structuremostofthetime.TheGherkinlanguageisbusinessreadableandwellknowninBDD.
TherearelotsofframeworksintheJavacommunitythatsupportBDDconcepts.CitrushasdedicatedsupportfortheCucumberframeworkbecauseCucumberiswellsuitedforextensionsandplugins.SowiththeCitrusandCucumberintegrationyoucanwriteGherkinsyntaxscenarioandfeaturestoriesinordertoexecutetheCitrusintegrationtestcapabilities.Asusualwehavealookatafirstexample.FirstletsseetheCitruscucumberdependencyandXMLschemadefinitions.
NoteTheCucumbercomponentsinCitrusarekeptinaseparateMavenmodule.IfnotalreadydonesoyouhavetoincludethemoduleasMavendependencytoyourproject
<dependency><groupId>com.consol.citrus</groupId><artifactId>citrus-cucumber</artifactId><version>2.7.1</version></dependency>
CitrusprovidesaseparateconfigurationnamespaceandschemadefinitionforCucumberrelatedstepdefinitions.IncludethisnamespaceintoyourSpringconfigurationinordertousetheCitrusCucumberconfigurationelements.ThenamespaceURIandschemalocationareaddedtotheSpringconfigurationXMLfileasfollows.
<spring:beansxmlns:spring="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://www.citrusframework.org/schema/cucumber/testcase"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.citrusframework.org/schema/cucumber/testcase
CitrusReferenceGuide
401Cucumber
![Page 402: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/402.jpg)
http://www.citrusframework.org/schema/cucumber/testcase/citrus-cucumber-testcase.xsd">
[...]
</spring:beans>
CucumberworkswithbothJUnitandTestNGasunittestingframework.YoucanchoosewhichframeworktousewithCucumber.SofollowingfromthatweneedaMavendependencyfortheunittestingframeworksupport:
<dependency><groupId>info.cukes</groupId><artifactId>cucumber-junit</artifactId><version>$cucumber.version</version></dependency>
InordertoenableCitrusCucumbersupportweneedtospecifyaspecialobjectfactoryintheenvironment.Themostcomfortablewaytospecifyacustomobjectfactoryistoaddthispropertytothecucumber.propertiesinclasspath.
cucumber.api.java.ObjectFactory=cucumber.runtime.java.CitrusObjectFactory
Thisspecialobjectfactorytakescareoncreatingallstepdefinitioninstances.Theobjectfactoryisabletoinject@CitrusResourceannotatedfieldsinstepclasses.Wewillseethislateronintheexamples.TheusageofthisspecialobjectfactoryismandatoryinordertocombineCitrusandCucumbercapabilities.
TheCitrusObjectFactorywillautomaticallyinitializetheCitrusworldforus.Thisincludesthedefaultcitrus-context.xmlCitrusSpringconfigurationthatisautomaticallyloadedwithintheobjectfactory.SoyoucandefineanduseCitruscomponentsasusualwithinyourtest.
AfterthesepreparationstepsyouareabletocombineCitrusandCucumberinyourproject.
Cucumberintegration
CucumberisabletoruntestswithJUnit.ThebasictestcaseisanemptytestwhichusestherespectiveJUnitrunnerimplementationfromcucumber.
CitrusReferenceGuide
402Cucumber
![Page 403: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/403.jpg)
@RunWith(Cucumber.class)@CucumberOptions(plugin="com.consol.citrus.cucumber.CitrusReporter")publicclassMyFeatureIT
ThetestcaseaboveusestheCucumberJUnittestrunner.InadditiontothatwegivesomeoptionstotheCucumberexecution.WedefineaspecialCitrusreporterimplementation.ThisclassisresponsibleforprintingtheCitrustestsummary.ThisreporterextendsthedefaultCucumberreporterimplementationsothedefaultCucumberreportsummariesarealsoprintedtotheconsole.
ThatcompletestheJUnitclassconfiguration.NowweareabletoaddfeaturestoriesandstepdefinitionstothepackageofourtestMyFeatureIT.CucumberandCitruswillautomaticallypickupstepdefinitionsandgluecodeinthattestpackage.Soletswriteafeaturestoryecho.featurerightnexttotheMyFeatureITtestclass.
Feature:Echoservice
Scenario:SayhelloGivenMynameisCitrusWhenIsayhellototheserviceThentheserviceshouldreturn:"Hello,mynameisCitrus!"
Scenario:SaygoodbyeGivenMynameisCitrusWhenIsaygoodbyetotheserviceThentheserviceshouldreturn:"GoodbyefromCitrus!"
AsyoucanseethisstorydefinestwoscenarioswiththeGherkinGiven-When-Thensyntax.NowweneedtoaddstepdefinitionsthatgluethestorydescriptiontoCitrustestactions.LetsdothisinanewclassEchoSteps.
publicclassEchoSteps
@CitrusResourceprotectedTestDesignerdesigner;
@Given("^Mynameis(.*)$")publicvoidmy_name_is(Stringname)designer.variable("username",name);
@When("^Isayhello.*$")
CitrusReferenceGuide
403Cucumber
![Page 404: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/404.jpg)
publicvoidsay_hello()designer.send("echoEndpoint").messageType(MessageType.PLAINTEXT).payload("Hello,mynameis$username!");
@When("^Isaygoodbye.*$")publicvoidsay_goodbye()designer.send("echoEndpoint").messageType(MessageType.PLAINTEXT).payload("Goodbyefrom$username!");
@Then("^theserviceshouldreturn:\"([^\"]*)\"$")publicvoidverify_return(finalStringbody)designer.receive("echoEndpoint").messageType(MessageType.PLAINTEXT).payload("Youjustsaid:"+body);
IfwehaveacloserlookatthestepdefinitionclassweseethatitisanormalPOJOthatusesa@CitrusResourceannotatedTestDesigner.ThetestdesignerisautomaticallyinjectedbyCitrusCucumberextension.Thisisdonebecausewehaveincludedthecitrus-cucumberdependencytoourprojectbefore.Nowwecanwrite@Given,@Whenor@Thenannotatedmethodsthatmatchthescenariodescriptionsinourstory.Cucumberwillautomaticallyfindmatchingmethodsandexecutethem.ThemethodsaddtestactionstothetestdesignerasweareusedtoitinnormalJavaDSLtests.Attheendthetestdesignerisautomaticallyexecutedwiththetestlogic.
ImportantOfcourseyoucandothedependencyinjectionwith@CitrusResourceannotationsonTestRunnerinstances,too.WhichvariationshouldsomeoneuseTestDesignerorTestRunner?Infactthereisasignificantdifferencewhenlookingatthetwoapproaches.ThedesignerwillusetheGherkinmethodstobuildthewholeCitrustestcasefirstbeforeanyactionisexecuted.TherunnerwillexecuteeachtestactionthathasbeenbuiltwithaGherkinstepimmediately.ThismeansthatadesignerapproachwillalwayscompleteallBDDstepdefinitionsbeforetakingaction.ThisdirectlyaffectstheCucumberstepreports.AllstepsareusuallymarkedassuccessfulwhenusingadesignerapproachastheCitrustestisexecutedaftertheCucumberstepshavebeenexecuted.Therunnerapproachincontrastwillfailthestepwhenthecorrespondingtestactionfails.TheCucumbertestreportswilldefinitelylookdifferent
CitrusReferenceGuide
404Cucumber
![Page 405: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/405.jpg)
dependingonwhatapproachyouarechoosing.Allotherfunctionsstaythesameinbothapproaches.Ifyouneedtolearnmoreaboutdesignerandrunnerapproachespleasesee
IfweruntheCucumbertesttheCitrustestcaseautomaticallyperformsitsactions.ThatisafirstcombinationofCitrusandCucumberBDD.Thestorydescriptionsaretranslatedtotestactionsandweareabletorunintegrationtestswithbehaviordrivendevelopment.Great!InanextstepwewilluseXMLstepdefinitionsratherthancodingthestepsinJavaDSL.
CucumberXMLsteps
SofarwehavewrittengluecodeinJavainordertotranslateGherkinsyntaxdescriptionstotestactions.NowwewanttodothesamewithjustXMLconfiguration.TheJUnitCucumberclassshouldnotchange.WestillusetheCucumberrunnerimplementationwithsomeoptionsspecifictoCitrus:
@RunWith(Cucumber.class)@CucumberOptions(plugin="com.consol.citrus.cucumber.CitrusReporter")publicclassMyFeatureIT
Thescenariodescriptionisalsonotchanged:
Feature:Echoservice
Scenario:SayhelloGivenMynameisCitrusWhenIsayhellototheserviceThentheserviceshouldreturn:"Hello,mynameisCitrus!"
Scenario:SaygoodbyeGivenMynameisCitrusWhenIsaygoodbyetotheserviceThentheserviceshouldreturn:"GoodbyefromCitrus!"
Inthefeaturepackagemy.company.featuresweaddanewXMLfileEchoSteps.xmlthatholdsthenewXMLstepdefinitions:
<?xmlversion="1.0"encoding="UTF-8"?><spring:beansxmlns:citrus="http://www.citrusframework.org/schema/testcase"
CitrusReferenceGuide
405Cucumber
![Page 406: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/406.jpg)
xmlns:spring="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://www.citrusframework.org/schema/cucumber/testcase"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.citrusframework.org/schema/cucumber/testcasehttp://www.citrusframework.org/schema/cucumber/testcase/citrus-cucumber-testcase.xsd"
<stepgiven="^Mynameis(.*)$"parameter-names="username"><citrus:create-variables><citrus:variablename="username"value="$username"/></citrus:create-variables></step>
<stepwhen="^Isayhello.*$"><citrus:sendendpoint="echoEndpoint"><citrus:messagetype="plaintext"><citrus:data>Hello,mynameis$username!</citrus:data></citrus:message></citrus:send></step>
<stepwhen="^Isaygoodbye.*$"><citrus:sendendpoint="echoEndpoint"><citrus:messagetype="plaintext"><citrus:data>Goodbyefrom$username!</citrus:data></citrus:message></citrus:send></step>
<stepthen="^theserviceshouldreturn:"([^"]*)"$"parameter-names="body"><citrus:receiveendpoint="echoEndpoint"><citrus:messagetype="plaintext"><citrus:data>Youjustsaid:$body</citrus:data></citrus:message></citrus:receive></step>
</spring:beans>
TheabovestepsdefinitioniswritteninpureXML.CitruswillautomaticallyreadthestepdefinitionandaddthosetotheCucumberruntime.Followingfromthatthestepdefinitionsareexecutedwhenmatchingtothefeaturestory.TheXMLstepfilesfollowanamingconvention.Citruswilllookforallfileslocatedinthefeaturepackagewithnamepattern**/.Steps.xml**andloadthosedefinitionswhenCucumberstartsup.
CitrusReferenceGuide
406Cucumber
![Page 407: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/407.jpg)
TheXMLstepsareabletoreceiveparametersfromtheGherkinregexpmatcher.Theparametersarepassedtothestepastestvariable.Theparameternamesgetdeclaredintheoptionalattributeparameter-names.Inthestepdefinitionactionsyoucanusetheparameternamesastestvariables.
NoteThetestvariablesarevisibleinallupcomingsteps,too.Thisisbecausethetestvariablesareglobalbydefault.Ifyouneedtosetlocalstateforastepdefinitionyoucanuseanotherattributeglobal-contextandsetittofalseinthestepdefinition.Thiswayalltestvariablesandparametersareonlyvisibleinthestepdefinition.Otherstepswillnotseethetestvariables.
NoteAnothernotablethingistheXMLescapingofreservedcharactersinthepatterndefinition.Youcanseethatinthelaststepwherethethenattributeisescapingquotationcharacters.
then="^theserviceshouldreturn:"([^"]*)"$"
WehavetodothisbecauseotherwisethequotationcharacterswillinterferewiththeXMLsyntaxintheattribute.
ThiscompletesthedescriptionofhowtoaddXMLstepdefinitionstothecucumberBDDtests.Inanextsectionwewillusepredefinedstepsforsendingandreceivingmessages.
CucumberSpringsupport
CucumberprovidessupportforSpringdependencyinjectioninstepdefinitionclasses.TheCucumberSpringcapabilitiesareincludedinaseparatemodule.Sowefirstofallwehavetoaddthisdependencytoourproject:
<dependency><groupId>info.cukes</groupId><artifactId>cucumber-spring</artifactId><version>$cucumber.version</version></dependency>
TheCitrusCucumberextensionhastohandlethingsdifferentwhenCucumberSpringsupportisenabled.ThereforeweuseanotherobjectfactoryimplementationthatalsosupportCucumberSpringfeatures.Changetheobjectfactorypropertyincucumber.propertiestothefollowing:
CitrusReferenceGuide
407Cucumber
![Page 408: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/408.jpg)
cucumber.api.java.ObjectFactory=cucumber.runtime.java.spring.CitrusSpringObjectFactory
Nowwearereadytoadd@AutowiredSpringbeandependenyinjectiontostepdefinitionclasses:
@ContextConfiguration(classes=CitrusSpringConfig.class)publicclassEchoSteps@AutowiredprivateEndpointechoEndpoint;
@CitrusResourceprotectedTestDesignerdesigner;
@Given("^Mynameis(.*)$")publicvoidmy_name_is(Stringname)designer.variable("username",name);
@When("^Isayhello.*$")publicvoidsay_hello()designer.send(echoEndpoint).messageType(MessageType.PLAINTEXT).payload("Hello,mynameis$username!");
@When("^Isaygoodbye.*$")publicvoidsay_goodbye()designer.send(echoEndpoint).messageType(MessageType.PLAINTEXT).payload("Goodbyefrom$username!");
@Then("^theserviceshouldreturn:\"([^\"]*)\"$")publicvoidverify_return(finalStringbody)designer.receive(echoEndpoint).messageType(MessageType.PLAINTEXT).payload("Youjustsaid:"+body);
AsyoucanseeweusedSpringautowiringmechanismfortheechoEndpointfieldinthestepdefinition.Alsobesuretodefinethe@ContextConfigurationannotationonthestepdefinition.TheCucumberSpringsupportloadstheSpringapplicationcontextandtakescareondependencyinjection.WeusetheCitrusCitrusSpringConfigJavaconfigurationbecausethisisthemainentranceforCitrustestcases.Youcanadd
CitrusReferenceGuide
408Cucumber
![Page 409: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/409.jpg)
custombeansandfurtherSpringrelatedconfigurationtothisSpringapplicationcontext.IfyouwanttoaddmorebeansforautowiringdosointheCitrusSpringconfiguration.Usuallythisisthedefaultcitrus-context.xmlwhichisautomaticallyloaded.
OfcourseyoucanalsouseacustomJavaSpringconfigurationclasshere.ButbesuretoalwaysimporttheCitrusSpringJavaconfigurationclasses,too.OtherwiseyouwillnotbeabletoexecutetheCitrusintegrationtestcapabilities.
Asusualweareabletouse@CitrusResourceannotatedTestDesignerfieldsforbuildingtheCitrusintegrationtestlogic.WiththisextensionyoucanusethefullSpringtestingpowerinyourtestsinparticulardependencyinjectionandalsotransactionmanagementfordatapersistancetests.
Citrusstepdefinitions
Citrusprovidessomeoutoftheboxpredefinedstepsfortypicalintegrationtestscenarios.Thesestepsarereadytouseinscenarioorfeaturestories.Youcanbasicallydefinesendandreceiveoperations.AsthesestepsarepredefinedinCitrusyoujustneedtowritefeaturestories.Thestepdefinitionswithgluetotestactionsarehandledautomatically.
Ifyouwanttoenablepredefinedstepssupportinyourtestyouneedtoincludethegluecodepackageinyourtestclasslikethis:
@RunWith(Cucumber.class)@CucumberOptions(glue="com.consol.citrus.cucumber.step.designer.core",plugin="com.consol.citrus.cucumber.CitrusReporter")publicclassMyFeatureIT
Insteadofwritingthegluecodeonourowninstepdefinitionclassesweincludethegluepackagecom.consol.citrus.cucumber.step.designer.core.ThisautomaticallyloadsallCitrusgluestepdefinitionsinthispackage.OnceyouhavedonethisyoucanusepredefinedstepsthataddCitrustestlogicwithouthavingtowriteanygluecodeinJavastepdefinitions.
OfcourseyoucanalsochoosetoincludetheTestRunnerstepdefinitionsbychoosingthegluepackagecom.consol.citrus.cucumber.step.runner.core.
@RunWith(Cucumber.class)
CitrusReferenceGuide
409Cucumber
![Page 410: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/410.jpg)
@CucumberOptions(glue="com.consol.citrus.cucumber.step.runner.core",plugin="com.consol.citrus.cucumber.CitrusReporter")publicclassMyFeatureIT
Followingbasicstepdefinitionsareincludedinthispackage:
Givenvariable[name]is"[value]"Givenvariables|[name1]|[value1]||[name2]|[value2]|
When<[endpoint-name]>sends"[message-payload]"Then<[endpoint-name]>shouldreceive(message-type)"[message-payload]"
When<[endpoint-name]>sends"""[message-payload]"""Then<[endpoint-name]>shouldreceive(message-type)"""[message-payload]"""
When<[endpoint-name]>receives(message-type)"[message-payload]"Then<[endpoint-name]>shouldsend"[message-payload]"
When<[endpoint-name]>receives(message-type)"""[message-payload]"""Then<[endpoint-name]>shouldsend"""[message-payload]"""
Onceagainitshouldbesaidthatthestepdefinitionsincludedinthispackageareloadedautomaticallyasgluecode.SoyoucanstarttowritefeaturestoriesinGherkinsyntaxthattriggerthepredefinedsteps.
Thereareseveraldefaultstepdefinitionsfordifferentaspectsofintegrationtesting.PleaseseethefollowingpackagesthatdefinedefaultstepsinCitrus:
Testdesignerpackages
com.consol.citrus.cucumber.step.designer.core
CitrusReferenceGuide
410Cucumber
![Page 411: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/411.jpg)
com.consol.citrus.cucumber.step.designer.httpcom.consol.citrus.cucumber.step.designer.dockercom.consol.citrus.cucumber.step.designer.selenium
Testrunnerpackages
com.consol.citrus.cucumber.step.runner.corecom.consol.citrus.cucumber.step.runner.httpcom.consol.citrus.cucumber.step.runner.dockercom.consol.citrus.cucumber.step.runner.selenium
InthefollowingsectionswehaveacloserlookatallpredefinedCitrusstepsandhowtheywork.
Variablesteps
AsyoualreadyknowCitrusisabletoworkwithtestvariablesthatholdimportantinformationduringatestsuchasidentifiersanddynamicvalues.ThepredefinedstepdefinitionsinCitrusareabletocreatenewtestvariables.
GivenvariablemessageTextis"Hello"
Thesyntaxofthispredefinedstepisprettyselfdescribing.Thestepinstructionfollowsthepattern:
Givenvariable[name]is"[value]"
Ifyoukeepthissyntaxinyourfeaturestorythepredefinedstepisactivatedforcreatinganewvariable.WealwaysusetheGivensteptocreatenewvariables.
Scenario:CreateVariablesGivenvariablemessageTextis"Hello"AndvariableoperationHeaderis"sayHello"
SowecanusetheAndkeywordtocreatemorethanonevariable.Evenmorecomfortableistheusageofdatatables:
Givenvariables|hello|Isayhello||goodbye|Isaygoodbye|
CitrusReferenceGuide
411Cucumber
![Page 412: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/412.jpg)
Thisdatatablewillcreatethetestvariableforeachrow.ThisishowyoucaneasilycreatenewvariablesinyourCitrustest.Asusualthevariablesarereferencedinmessagepayloadsandheadersasplaceholdersfordynamicallyaddingcontent.
AddingvariablesisusuallydonewithinaScenarioblockinyourfeaturestory.ThismeansthatthetestvariableisusedinthisscenariowhichisexactlyoneCitrustestcase.CucumberBDDalsodefinesaBackgroundblockattheverybeginningofyourFeature.Wecanalsoplacevariablesinhere.ThismeansthatCucumberwillexecutethesestepsforallupcomingscenarios.Thetestvariableissotospeakglobalforthisfeaturestory.
Feature:Variables
Background:GivenvariablemessageTextis"Hello"
Scenario:DosomethingScenario:Dosomethingelse
ThatcompletesthevariablestepdefinitionsinCitrus.
Messagingsteps
IntheprevioussectionwehavelearnedhowtouseafirstpredefinedCitrusstep.NowwewanttocovermessagingstepsforsendingandreceivingmessagesinCitrus.Asusualwithpredefinedstepsyoudonotneedtowriteanygluecodeforthestepstotakeaction.ThestepsarealreadyincludedinCitrusjustusetheminyourfeaturestories.
Feature:Messagingfeatures
Background:GivenvariablemessageTextis"Hello"
Scenario:SendandreceiveplaintextWhen<echoEndpoint>sends"$messageText"Then<echoEndpoint>shouldreceiveplaintext"Youjustsaid:$messageText"
Ofcourseweneedtofollowthepredefinedsyntaxwhenwritingfeaturestoriesinordertotriggerapredefinedstep.Let'shaveacloserlookatthispredefinedsyntaxbyfurtherdescribingtheaboveexample.
CitrusReferenceGuide
412Cucumber
![Page 413: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/413.jpg)
FirstofallwedefineanewtestvariablewithGivenvariablemessageTextis"Hello".ThistellsCitrustocreateanewtestvariablenamedmessageTextwithrespectivevalue.Wecandothesameforsendingandreceivingmessageslikedoneinourtestscenario:
When<[endpoint-name]>sends"[message-payload]"
Thestepdefinitionrequirestheendpointcomponentnameandamessagepayload.ThepredefinedstepwillautomaticallyconfigureasendtestactionintheCitrustestasresult.
Then<[endpoint-name]>shouldreceive(message-type)"[message-payload]"
Thepredefinedreceivestepalsorequirestheendpoint-nameandmessage-payload.Asoptionalparameteryoucandefinethemessage-type.ThisisrequiredwhensendingmessagepayloadsotherthanXML.
ThiswayyoucanwriteCitrustestswithjustwritingfeaturestoriesinGherkinsyntax.Uptonowwehaveusedprettysimplemessagepayloadsinonsingleline.Ofcoursewecanalsousemultilinepayloadsinthestories:
Feature:Messagingfeatures
Background:GivenvariablemessageTextis"Hello"
Scenario:SendandreceiveWhen<echoEndpoint>sends"""<message><text>$messageText</text></message>"""Then<echoEndpoint>shouldreceive"""<message><text>$messageText</text></message>"""
AsyoucanseeweareabletousethesendandreceivestepswithmultilineXMLmessagepayloaddata.
Namedmessages
CitrusReferenceGuide
413Cucumber
![Page 414: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/414.jpg)
IntheprevioussectionwehavelearnedhowtouseCitruspredefinedstepdefinitionsforsendandreceiveoperations.Themessagepayloadhasbeenaddeddirectlytothestoriessofar.Butwhatiswithmessageheaderinformation?Wewanttospecifyacompletemessagewithpayloadandheader.Youcandothisbydefininganamedmessage.
Asusualwedemonstratethisinafirstexample:
Feature:Namedmessagefeature
Background:GivenmessageechoRequestAnd<echoRequest>payloadis"HimynameisCitrus!"And<echoRequest>headeroperationis"sayHello"
GivenmessageechoResponseAnd<echoResponse>payloadis"Hi,Citrushowareyoudoingtoday?"And<echoResponse>headeroperationis"sayHello"
Scenario:SendandreceiveWhen<echoEndpoint>sendsmessage<echoRequest>Then<echoEndpoint>shouldreceivemessage<echoResponse>
IntheBackgroundsectionweintroducenamedmessagesechoRequestandechoResponse.Thismakesuseofthenewpredefinedstepforaddingnamedmessage:
Givenmessage[message-name]
Oncethemessageisintroducedwithitsnamewecanusethemessageinfurtherconfigurationsteps.Youcanaddpayloadinformationandyoucanaddmultipleheaderstothemessage.Thenamedmessagethenisreferencedinsendandreceivestepsasfollows:
When<[endpoint-name]>sendsmessage<[message-name]>Then<[endpoint-name]>shouldreceivemessage<[message-name]>
ThestepsreferenceamessagebyitsnameechoRequestandechoResponse.
Asyoucanseethenamedmessagesareusedtodefinecompletemessageswithpayloadandheaderinformation.Ofcoursethenamedmessagescanbereferencedinmanyscenariosandsteps.Alsowithusageoftestvariablesinpayloadandheaderyou
CitrusReferenceGuide
414Cucumber
![Page 415: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/415.jpg)
candynmaicallyadjustthosemessagesineachstep.
Messagecreatorsteps
Intheprevioussectionwehavelearnedhowtousenamedmessagesaspredefinedstep.Thenamedmessagehasbeendefineddirectlyinthestoriessofar.ThemessagecreatorconceptmovesthistasktosomeJavaPOJO.Thiswayyouareabletoconstructmorecomplicatedmessagesforreuseinseveralscenariosandfeaturestories.
Asusualwedemonstratethisinafirstexample:
Feature:Messagecreatorfeatures
Background:Givenmessagecreatorcom.consol.citrus.EchoMessageCreatorAndvariablemessageTextis"Hello"Andvariableoperationis"sayHello"
Scenario:SendandreceiveWhen<echoEndpoint>sendsmessage<echoRequest>Then<echoEndpoint>shouldreceivemessage<echoResponse>
IntheBackgroundsectionweintroduceamessagecreatorEchoMessageCreatorinpackagecom.consol.citrus.Thismakesuseofthenewpredefinedstepforaddingmessagecreatorstothetest:
Givenmessagecreator[message-creator-name]
ThemessagecreatornamemustbethefullyqualifiedJavaclassnamewithpackageinformation.Oncethisisdonewecanusenamedmessagesinthesendandreceiveoperations:
When<[endpoint-name]>sendsmessage<[message-name]>Then<[endpoint-name]>shouldreceivemessage<[message-name]>
ThestepsreferenceamessagebyitsnameechoRequestandechoResponse.NowletshavealookatthemessagecreatorEchoMessageCreatorimplementationinordertoseehowthiscorrelatestoarealmessage.
publicclassEchoMessageCreator@MessageCreator("echoRequest")publicMessagecreateEchoRequest()
CitrusReferenceGuide
415Cucumber
![Page 416: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/416.jpg)
returnnewDefaultMessage(""+"$messageText"+"").setHeader("operation","$operation");
@MessageCreator("echoResponse")publicMessagecreateEchoResponse()returnnewDefaultMessage(""+"$messageText"+"").setHeader("operation","$operation");
AsyoucanseethemessagecreatorisaPOJOJavaclassthatdefinesoneormoremethodsthatareannotatedwith@MessageCreatorannotation.Theannotationrequiresamessagename.ThisishowCitruswillcorrelatemessagenamesinfeaturestoriestomessagecreatormethods.Themessagereturnedistheusedforthesendandreceiveoperationsinthetest.Themessagecreatorisreusableaccrossmultiplefeaturestoriesandscenarios.Inadditiontothatthecreatorisabletoconstructmessagesinamorepowerfulway.Forinstancethemessagepayloadcouldbeloadedfromfilesystemresources.
Echosteps
AnotherpredefinedstepdefinitioninCitrusisusedtoaddaechotestaction.Youcanusethefollowingstepinyourfeaturescenarios:
Feature:Echofeatures
Scenario:EchomessagesGivenvariablefoois"bar"Thenecho"Variablefoo=$foo"Thenecho"Todayiscitrus:currentDate()"
Thestepdefinitionrequiresfollowingpattern:
Thenecho"[message]"
Sleepsteps
Youcanaddsleeptestactionstothefeaturescenarios:
CitrusReferenceGuide
416Cucumber
![Page 417: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/417.jpg)
Feature:Sleepfeatures
Scenario:SleepdefaulttimeThensleep
Scenario:SleepmillisecondstimeThensleep200ms
Thestepdefinitionrequiresoneofthefollowingpatterns:
ThensleepThensleep[time]ms
ThisaddsanewsleeptestactiontotheCitrustest.
Httpsteps
TheHttpstepsarespeciallydesignedforHttpclient-servercommunication.YoucanusethesestepsbyaddingfollowingpackagesasglueoptionsinyourCucumbertest:
com.consol.citrus.cucumber.step.(designer|runner).http
ThispackagecontainsHttpspecificstepsthatenableyoutosendandreceivemessagesviaHttpREST:
Feature:VotingHttpRESTAPI
Background:GivenURL:http://localhost:8080/rest/servicesGivenvariables|id|citrus:randomUUID()||title|DoyoulikeMondays?||options|["name":"yes","votes":0,"name":"no","votes":0]||report|true|
Scenario:ClearvotinglistWhensendDELETE/votingThenreceivestatus200OK
Scenario:GetemptyvotinglistGivenAccept:application/jsonWhensendGET/votingThenResponse:[]Andreceivestatus200OK
Scenario:Createvoting
CitrusReferenceGuide
417Cucumber
![Page 418: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/418.jpg)
GivenRequest:""""id":"$id","title":"$title","options":$options,"report":$report"""AndContent-Type:application/jsonWhensendPOST/votingThenreceivestatus200OK
Scenario:GetvotinglistWhensendGET/votingThenvalidate$.size()is1Thenvalidate$..titleis$titleThenvalidate$..reportis$reportAndreceivestatus200OK
ThefeaturescenariosusedefaultHttpstepstosendrequestswithdifferentmethods(GET,POST,PUT,DELETE)andreceivestatusresponses(Http200OK).Pleaseexplorethedefaultstepdefinitionsintherespectivepackagetogetadetailedunderstandingonhowtousethoseinyourfeaturespecification.
Dockersteps
Dockerstepsaccesscontainersandbuildimages.BydefaultthestepstrytofindavalidaDockerClientcomponentintheSpringapplicationcontextconfiguration.Youcanusethestepsinfeaturespecificationstomanagecontainerstates.
Feature:VotingDockerinfrastructure
Scenario:CheckcontainerdeploymentstateGivendocker-client"dockerClient"Thencontainer"voting-app"shouldberunningAndcontainer"message-broker"shouldberunning
Weareabletocheckthecontainerstaterunning.AllweneedistheDockercontainernameorid.WhatelsecanwedowithinthedefaultDockersteps?Wecanbuildnewimages:
Feature:Buildimages
Scenario:Buildvotingimage
CitrusReferenceGuide
418Cucumber
![Page 419: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/419.jpg)
Givendocker-client"dockerClient"Whenbuildimage"voting:1.0.0"fromfile"scr/main/docker/Dockerfile"Thencreatecontainer"voting-app"from"voting:1.0.0"Andcontainer"voting-app"shouldberunning
ThisishowwecanuseDockercommandsinCucumberfeaturespecificationswithCitrusdefaultstepdefinitions.AlldefaultstepdefinitionsforDockerarelocatedinpackage
com.consol.citrus.cucumber.step.(designer|runner).docker
Seleniumsteps
SeleniumisawidelyusedUIautomationframeworkwherebrowseruserinteractionsaresimulated.WecanusedefaultSeleniumstepsinthefeaturespecificationsinordertoaccessSeleniumcommandsinourtests.
Feature:Votinguserinterface
Background:GivenuserstartsbrowserAndusernavigatesto"http://localhost:8080"
Scenario:WelcomepageThenpageshoulddisplaylinkwithlink-text="Runapplication"
Scenario:StartapplicationWhenuserclickslinkwithlink-text="Runapplication"Andsleep500msThenpageshoulddisplayheadingwithtag-name="h1"having|text|Votinglist|
Andpageshoulddisplaylinkwithlink-text="Novotingfound"Andpageshoulddisplayformwithid="new-voting"having|tag-name|form||attribute|method="post"|
Scenario:AddvotingGivenusernavigatesto"http://localhost:8080/voting"Whenusersetstext"Doyoulikeburgers?"toinputwithid="title"Anduserclicksbuttonwithid="submitNew"Andsleep500msThenpageshoulddisplayelementwithlink-text="Doyoulikeburgers?"
CitrusReferenceGuide
419Cucumber
![Page 420: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/420.jpg)
WiththepredefinedCucumberstepsforSeleniumweareabletointeractwiththebrowser.Forinstancewecanclickbuttons,verifypageobjectsandnavigatetodifferentpages.
AlltheseSeleniumstepsarelocatedinpackage:
com.consol.citrus.cucumber.step.(designer|runner).selenium
TheSeleniumbrowserisautomaticallypickedfromtheSpringbeanapplicationcontextconfigurationinCitrus.HereyoucandecidewhichSeleniumWebDrivertouseduringthetests.Alsoyoucaninstantiatewebpageinstancesandcallpageactionsandvalidationsteps:
publicclassVotingListPageimplementsWebPage,PageValidator<VotingListPage>
@FindBy(tagName="h1")privateWebElementheading;
@FindBy(id="new-voting")privateWebElementnewVotingForm;
/***Submitsnewvoting.*@paramtitle*@paramoptions*/publicvoidsubmit(Stringtitle,Stringoptions)newVotingForm.findElement(By.id("title")).sendKeys(title);if(StringUtils.hasText(options))newVotingForm.findElement(By.id("options")).sendKeys(options.replaceAll(":","\n"
newVotingForm.submit();
@Overridepublicvoidvalidate(VotingListPagewebPage,SeleniumBrowserbrowser,TestContextcontext)Assert.assertEquals("Votinglist",heading.getText());
Thispageobjectdefineselementsandactionsonthatpagethatarecallableinourfeaturespecification.
Feature:Votingpages
CitrusReferenceGuide
420Cucumber
![Page 421: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/421.jpg)
Background:Givenpage"welcomePage"com.consol.citrus.demo.voting.selenium.pages.WelcomePageGivenpage"votingListPage"com.consol.citrus.demo.voting.selenium.pages.VotingListPage
Scenario:WelcomepageWhenuserstartsbrowserAndusernavigatesto"http://localhost:8080"ThenpagewelcomePageshouldvalidate
Scenario:StartapplicationWhenusernavigatesto"http://localhost:8080"AndpagewelcomePageperformsstartAppAndsleep500msThenpagevotingListPageshouldvalidate
Scenario:AddvotingGivenusernavigatesto"http://localhost:8080/voting"WhenpagevotingListPageperformssubmitwitharguments|Doyoulikepizza?|Andsleep500msThenpageshoulddisplayelementwithlink-text="Doyoulikepizza?"AndpagevotingListPageshouldvalidate
Scenario:AddvotingwithoptionsGivenusernavigatesto"http://localhost:8080/voting"WhenpagevotingListPageperformssubmitwitharguments|Whatisyourfavoritecolor?||red:green:blue|Andsleep500msThenpageshoulddisplayelementwithlink-text="Whatisyourfavoritecolor?"AndpagevotingListPageshouldvalidate
Thepageobjectsgetinstantiatedanddependencyinjectionmakessurethatwebelementsandotherresourcesarepassedtothepageobject.Thenactionmethodcanperformaswellasvalidationtaskscanvalidatethepagestate.
CitrusReferenceGuide
421Cucumber
![Page 422: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/422.jpg)
ZookeepersupportCitrusprovidesconfigurationcomponentsandtestactionsforinteractingwithZookeeper.TheCitrusZookeeperclientcomponentexecutescommandslikecreate-node,checknode-exists,delete-node,getnode-dataorsetnode-data.AsauseryoucanexecuteZookeepercommandsaspartofaCitrustestandvalidatepossiblecommandresults.
NoteTheZookeepertestcomponentsinCitrusarekeptinaseparateMavenmodule.IfnotalreadydonesoyouhavetoincludethemoduleasMavendependencytoyourproject
<dependency><groupId>com.consol.citrus</groupId><artifactId>citrus-zookeeper</artifactId><version>2.7.1</version></dependency>
Citrusprovidesa"citrus-zookeeper"configurationnamespaceandschemadefinitionforZookeeperrelatedcomponentsandactions.IncludethisnamespaceintoyourSpringconfigurationinordertousetheCitruszookeeperconfigurationelements.ThenamespaceURIandschemalocationareaddedtotheSpringconfigurationXMLfileasfollows.
<beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:citrus-zookeeper="http://www.citrusframework.org/schema/zookeeper/config"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.citrusframework.org/schema/zookeeper/confighttp://www.citrusframework.org/schema/zookeeper/config/citrus-zookeeper-config.xsd">
[...]
</beans>
AfterthatyouareabletousecustomizedCitrusXMLelementsinordertodefinetheSpringbeans.
CitrusReferenceGuide
422Zookeeper
![Page 423: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/423.jpg)
Zookeeperclient
BeforeyoucaninteractwithaZookeeperserveryouhavetoconfiguretheZookeeperclient.Asampleconfigurationisprovidedbelowdescribingtheconfigurationoptionsavailable:
<citrus-zookeeper:clientid="zookeeperClient"url="http://localhost:21118"timeout="2000"/>
ThisisatypicalclientconfigurationforconnectingtoaZookeeperserver.Nowyouareabletoexecuteseveralcommands.ThesecommandswillbesenttotheZookeeperserverforexecution.
Zookeepercommands
SeebelowallavailableZookeepercommandsthataCitrusclientisabletoexecute.
info:Retrievesthecurrentstateoftheclientconnectioncreate:CreatesaznodeinaspecifiedpathoftheZooKeepernamespacedelete:DeletesaznodefromaspecifiedpathoftheZooKeepernamespaceexists:Checksifaznodeexistsinthepathchildren:Getsalistofchildrenofaznodeget:Getsthedataassociatedwithaznodeset:Sets/writesdataintothedatafieldofaznode
BeforeweseesomeofthesecommandsinactionwehavetoaddanewtestnamespacetoourtestcasewhenusingtheXMLDSL.
<beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:zookeeper="http://www.citrusframework.org/schema/zookeeper/testcase"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.citrusframework.org/schema/zookeeper/testcasehttp://www.citrusframework.org/schema/zookeeper/testcase/citrus-zookeeper-testcase.xsd"
[...]
</beans>
CitrusReferenceGuide
423Zookeeper
![Page 424: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/424.jpg)
WeaddedtheZookeepernamespacewithprefixzookeeper:sonowwecanstarttoaddspecialtestactionstothetestcase:
XMLDSL
<zookeeper:createzookeeper-client="zookeeperClient"path="/$randomString"acl="OPEN_ACL_UNSAFE"<zookeeper:data>foo</zookeeper:data><zookeeper:expect><zookeeper:result><![CDATA["responseData":"path":"/$randomString"]]></zookeeper:result></zookeeper:expect></zookeeper:create>
<zookeeper:getzookeeper-client="zookeeperClient"path="/$randomString"><zookeeper:expect><zookeeper:result><![CDATA["responseData":"data":"foo"]]></zookeeper:result></zookeeper:expect></zookeeper:getData>
<zookeeper:setzookeeper-client="zookeeperClient"path="/$randomString"><zookeeper:data>bar</zookeeper:data></zookeeper:setData>
WhenusingtheJavaDSLwecandirectlyconfigurethecommandswithafluentAPI.
JavaDSLdesignerandrunner
@CitrusTestpublicvoidtestZookeeper()variable("randomString","citrus:randomString(10)");
zookeeper().create("/$randomString","foo")
CitrusReferenceGuide
424Zookeeper
![Page 425: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/425.jpg)
.acl("OPEN_ACL_UNSAFE").mode("PERSISTENT").validateCommandResult(newCommandResultCallback<ZooResponse>()@OverridepublicvoiddoWithCommandResult(ZooResponseresult,TestContextcontext)Assert.assertEquals(result.getResponseData().get("path"),context.replaceDynamicContentInString("/$randomString")););
zookeeper().get("/$randomString").validateCommandResult(newCommandResultCallback<ZooResponse>()@OverridepublicvoiddoWithCommandResult(ZooResponseresult,TestContextcontext)Assert.assertEquals(result.getResponseData().get("version"),0););
zookeeper().set("/$randomString","bar");
TheexamplesabovecreateanewznodeinZookeeperusingarandomStringaspath.WecangetandsetthedatawithexpectingandvalidatingtheresultoftheZookeeperserver.ThisisbasicallytheideaofintegratingZookepperoperationstoaCitrustest.ThisopensthegatetomanageZookeeperrelatedentitieswithinaCitrustest.WecanmanipulateandvalidatetheznodesontheZookeeperinstance.
Zookeeperkeepsitsnodesinahierarchicalstorage.Thismeansaznodecanhavechildrenandwecanaddandremovethose.InCitrusyoucangetallchildrenofaznodeandmanagethosewithinthetest:
XMLDSL
<zookeeper:createzookeeper-client="zookeeperClient"path="/$randomString/child1"acl="OPEN_ACL_UNSAFE"<zookeeper:data></zookeeper:data><zookeeper:expect><zookeeper:result><![CDATA["responseData":"path":"/$randomString/child1"]]></zookeeper:result></zookeeper:expect>
CitrusReferenceGuide
425Zookeeper
![Page 426: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/426.jpg)
</zookeeper:create>
<zookeeper:createzookeeper-client="zookeeperClient"path="/$randomString/child2"acl="OPEN_ACL_UNSAFE"<zookeeper:data></zookeeper:data><zookeeper:expect><zookeeper:result><![CDATA["responseData":"path":"/$randomString/child2"]]></zookeeper:result></zookeeper:expect></zookeeper:create>
<zookeeper:childrenzookeeper-client="zookeeperClient"path="/$randomString"><zookeeper:expect><zookeeper:result><![CDATA["responseData":"children":["child1","child2"]]]></zookeeper:result></zookeeper:expect></zookeeper:children>
JavaDSLdesignerandrunner
zookeeper().create("/$randomString/child1","").acl("OPEN_ACL_UNSAFE").mode("PERSISTENT").validateCommandResult(newCommandResultCallback<ZooResponse>()@OverridepublicvoiddoWithCommandResult(ZooResponseresult,TestContextcontext)Assert.assertEquals(result.getResponseData().get("path"),context.replaceDynamicContentInString("/$randomString/child1")););
zookeeper().create("/$randomString/child2","").acl("OPEN_ACL_UNSAFE").mode("PERSISTENT").validateCommandResult(newCommandResultCallback<ZooResponse>()
CitrusReferenceGuide
426Zookeeper
![Page 427: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/427.jpg)
@OverridepublicvoiddoWithCommandResult(ZooResponseresult,TestContextcontext)Assert.assertEquals(result.getResponseData().get("path"),context.replaceDynamicContentInString("/$randomString/child2")););
zookeeper().children("/$randomString").validateCommandResult(newCommandResultCallback<ZooResponse>()@OverridepublicvoiddoWithCommandResult(ZooResponseresult,TestContextcontext)Assert.assertEquals(result.getResponseData().get("children").toString(),"[child1,child2]"););
CitrusReferenceGuide
427Zookeeper
![Page 428: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/428.jpg)
SpringRestdocssupportSpringRestdocsprojecthelpstoeasilygenerateAPIdocumentationforRESTfulservices.WhilemessagesareexchangedtheRestdocslibrarygeneratesrequest/responsesnippetsandAPIdocumentation.YoucanaddtheSpringRestdocsdocumentationtotheCitrusclientcomponentsforHttpandSOAPendpoints.
NoteTheSpringRestdocssupportcomponentsinCitrusarekeptinaseparateMavenmodule.IfnotalreadydonesoyouhavetoincludethemoduleasMavendependencytoyourproject
<dependency><groupId>com.consol.citrus</groupId><artifactId>citrus-restdocs</artifactId><version>2.7.1</version></dependency>
ForeasyconfigurationCitrushascreatedaseparatenamespaceandschemadefinitionforSpringRestdocsrelateddocumentation.IncludethisnamespaceintoyourSpringconfigurationinordertousetheCitrusRestdocsconfigurationelements.ThenamespaceURIandschemalocationareaddedtotheSpringconfigurationXMLfileasfollows.
<spring:beansxmlns:spring="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://www.citrusframework.org/schema/cucumber/testcase"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.citrusframework.org/schema/restdocs/confighttp://www.citrusframework.org/schema/restdocs/config/citrus-restdocs-config.xsd">
[...]
</spring:beans>
AfterthatyouareabletousecustomizedCitrusXMLelementsinordertodefinetheSpringbeans.
SpringRestdocsusingHttp
CitrusReferenceGuide
428Restdocs
![Page 429: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/429.jpg)
FirstofallweconcentrateonaddingtheSpringRestdocsfeaturetoHttpclientcommunication.ThenextsampleconfigurationusesthenewSpringRestdocscomponentsinCitrus:
<citrus-restdocs:documentationid="restDocumentation"output-directory="test-output/generated-snippets"identifier="rest-docs/method-name"/>
Theabovecomponentaddsanewdocumentationconfiguration.Behindthescenesthecomponentcreatesanewrestdocsconfigurerandaclientinterceptor.Wecanreferencethenewrestdocscomponentincitrus-httpclientcomponentslikethis:
<citrus-http:clientid="httpClient"request-url="http://localhost:8080/test"request-method="POST"interceptors="restDocumentation"/>
TheSpringRestdocsdocumentationcomponentactsasaclientinterceptor.EverytimetheclientcomponentisusedtosendandreceiveamessagetherestdocsinterceptorwillautomaticallycreateitsAPIdocumentation.Theconfigurationidentifierattributedescribestheoutputformatrest-docs/method-namewhichresultsinafolderlayoutlikethis:
test-output|-rest-docs|-test-a|-curl-request.adoc|-http-request.adoc|-http-response.adoc|-test-b|-curl-request.adoc|-http-request.adoc|-http-response.adoc|-test-c|-curl-request.adoc|-http-request.adoc|-http-response.adoc
TheexampleaboveistheresultofthreetestcaseseachofthemperformingaclientHttprequest/responsecommunication.Eachtestmessageexchangeisdocumentedwithseparatefiles:
CitrusReferenceGuide
429Restdocs
![Page 430: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/430.jpg)
curl-request.adoc
[source,bash]----$curl'http://localhost:8080/test'-i-XPOST-H'Accept:application/xml'-H'CustomHeaderId:123456789'-H'Content-Type:application/xml;charset=UTF-8'-H'Accept-Charset:utf-8'-d'>testRequestMessage>>text>HelloHttpServer>/text>>/testRequestMessage>'----
Thecurlfilerepresentstheclientrequestascurlcommandandcanbeseenasasampletoreproducetherequest.
http-request.adoc
[source,http,options="nowrap"]----POST/testHTTP/1.1Accept:application/xmlCustomHeaderId:123456789Content-Type:application/xml;charset=UTF-8Content-Length:118Accept-Charset:utf-8Host:localhost
>testRequestMessage>>text>HelloHttpServer>/text>>/testRequestMessage>----
Thehttp-request.adocfilerepresentsthesentmessagedatafortheclientrequest.Therespectivehttp-response.adocrepresentstheresponsethatwassenttotheclient.
http-response.adoc
[source,http,options="nowrap"]----HTTP/1.1200OKDate:Tue,07Jun201612:10:46GMTContent-Type:application/xml;charset=UTF-8Accept-Charset:utf-8Content-Length:122Server:Jetty(9.2.15.v20160210)
>testResponseMessage>>text>HelloCitrus!>/text>>/testResponseMessage>
CitrusReferenceGuide
430Restdocs
![Page 431: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/431.jpg)
----
Nicework!WehaveautomaticallycreatedsnippetsfortheRESTfulAPIbyjustaddingtheinterceptortotheCitrusclientcomponent.SpringRestdocscomponentscanbecombinedmanually.Seethenextconfigurationthatusesthisapproach.
<citrus-restdocs:configurerid="restDocConfigurer"output-directory="test-output/generated-snippets"<citrus-restdocs:client-interceptorid="restDocClientInterceptor"identifier="rest-docs/method-name"
<util:listid="restDocInterceptors"><refbean="restDocConfigurer"/><refbean="restDocClientInterceptor"/></util:list>
<citrus-http:clientid="httpClient"request-url="http://localhost:8080/test"request-method="POST"interceptors="restDocInterceptors"/>
Whatexactlyisthedifferencetothecitrus-restdocs:documentationthatwehaveusedbefore?Ingeneralthereisnodifference.Bothconfigurationsareidenticalinitsoutcome.Whyshouldsomeoneusethesecondapproachthen?Itismoreverboseasweneedtoalsodefinealistofinterceptors.Theansweriseasy.Ifyouwanttocombinetherestdocsinterceptorswithotherclientinterceptorsinalistthenyoushouldusethemanualcombinationapproach.Wecanaddbasicauthenticationinterceptorsforinstancetothelistofinterceptorsthen.Themorecomfortablecitrus-restdocs:documentationcomponentonlysupportsexclusiverestdocsinterceptors.
SpringRestdocsusingSOAP
YoucanusetheSpringRestdocsfeaturesalsoforSOAPclientsinCitrus.ThisisacontroversyideaasSOAPendpointsaredifferenttoRESTfulconcepts.ButattheendSOAPHttpcommunicationisHttpcommunicationwithrequestandresponsemessages.Whyshouldwemissoutthefantasticdocumentationfeatureherejustbecauseofideologyreasons.
TheconceptofaddingtheSpringRestdocsdocumentationasinterceptortotheclientisstillthesame.
<citrus-restdocs:documentationid="soapDocumentation"
CitrusReferenceGuide
431Restdocs
![Page 432: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/432.jpg)
type="soap"output-directory="test-output/generated-snippets"identifier="soap-docs/method-name"/>
Wehaveaddedatypesettingwithvaluesoap.Andthatisbasicallyallweneedtodo.NowCitrusknowsthatwewouldliketoadddocumentationforaSOAPclient:
<citrus-ws:clientid="soapClient"request-url="http://localhost:8080/test"interceptors="soapDocumentation"/>
FollowingfromthatthesoapClientisenabledtogenerateSpringRestdocsdocumentationforeachrequest/response.ThegeneratedsnippetsthendorepresenttheSOAPrequestandresponsemessages.
http-request.adoc
[source,http,options="nowrap"]----POST/testHTTP/1.1SOAPAction:"test"Accept:application/xmlCustomHeaderId:123456789Content-Type:application/xml;charset=UTF-8Content-Length:529Accept-Charset:utf-8Host:localhost
>SOAP-ENV:Envelopexmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">>SOAP-ENV:Header>>Operationxmlns="http://citrusframework.org/test">sayHello>/Operation>>/SOAP-ENV:Header>>SOAP-ENV:Body>>testRequestMessage>>text>HelloHttpServer>/text>>/testRequestMessage>>/SOAP-ENV:Body>>/SOAP-ENV:Envelope>----
http-response.adoc
[source,http,options="nowrap"]----HTTP/1.1200OK
CitrusReferenceGuide
432Restdocs
![Page 433: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/433.jpg)
Date:Tue,07Jun201612:10:46GMTContent-Type:application/xml;charset=UTF-8Accept-Charset:utf-8Content-Length:612Server:Jetty(9.2.15.v20160210)
>SOAP-ENV:Envelopexmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">>SOAP-ENV:Header>>Operationxmlns="http://citrusframework.org/test">sayHello>/Operation>>/SOAP-ENV:Header>>SOAP-ENV:Body>>testResponseMessage>>text>HelloCitrus!>/text>>/testResponseMessage>>/SOAP-ENV:Body>>/SOAP-ENV:Envelope>----
Thefilenamesarestillusinghttp-requestandhttp-responsebutthecontentisclearlytheSOAPrequest/responsemessagedata.
SpringRestdocsinJavaDSL
HowcanweuseSpringRestdocsinJavaDSL?OfcoursewehavespecialsupportinCitrusJavaDSLfortheSpringRestdocsconfiguration,too.
JavaDSL
publicclassRestDocConfigurationITextendsTestNGCitrusTestDesigner
@AutowiredprivateTestListenerstestListeners;
privateHttpClienthttpClient;
@BeforeClasspublicvoidsetup()CitrusRestDocConfigurerrestDocConfigurer=CitrusRestDocsSupport.restDocsConfigurer(newManualRestDocumentation("target/generated-snippets"));RestDocClientInterceptorrestDocInterceptor=CitrusRestDocsSupport.restDocsInterceptor("rest-docs/method-name");
httpClient=CitrusEndpoints.http().client().requestUrl("http://localhost:8073/test").requestMethod(HttpMethod.POST).contentType("text/xml").interceptors(Arrays.asList(restDocConfigurer,restDocInterceptor)).build();
CitrusReferenceGuide
433Restdocs
![Page 434: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/434.jpg)
testListeners.addTestListener(restDocConfigurer);
@Test@CitrusTestpublicvoidtestRestDocs()http().client(httpClient).send().post().payload("<testRequestMessage>"+"<text>HelloHttpServer</text>"+"</testRequestMessage>");
http().client(httpClient).receive().response(HttpStatus.OK).payload("<testResponseMessage>"+"<text>HelloTestFramework</text>"+"</testResponseMessage>");
ThemechanismisquitesimilartotheXMLconfiguration.WeaddtheRestdocsconfigurerandinterceptortothelistofinterceptorsfortheHttpclient.Ifwedothisallclientcommunicationisautomaticallydocumented.TheCitrusJavaDSLprovidessomeconvenientconfigurationmethodsinclassCitrusRestDocsSupportforcreatingtheconfigurerandinterceptorobjects.
NoteTheconfigurermustbeaddedtothelistoftestlisteners.Thisisamandatorystepinordertoenabletheconfigurerfordocumentationpreparationsbeforeeachtest.Otherwisewewouldnotbeabletogenerateproperdocumentation.IfyouareusingtheXMLconfigurationthisisdoneautomaticallyforyou.
CitrusReferenceGuide
434Restdocs
![Page 435: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/435.jpg)
SeleniumsupportSeleniumisaverypopulartoolfortestinguserinterfaceswithbrowserautomation.CitrusisabletointegratewiththeSeleniumJavaAPIinordertoexecuteSeleniumcommands.
NoteTheSeleniumtestcomponentsinCitrusarekeptinaseparateMavenmodule.IfnotalreadydonesoyouhavetoincludethemoduleasMavendependencytoyourproject
<dependency><groupId>com.consol.citrus</groupId><artifactId>citrus-selenium</artifactId><version>2.7.1</version></dependency>
Citrusprovidesa"citrus-selenium"configurationnamespaceandschemadefinitionforSeleniumrelatedcomponentsandactions.IncludethisnamespaceintoyourSpringconfigurationinordertousetheCitrusSeleniumconfigurationelements.ThenamespaceURIandschemalocationareaddedtotheSpringconfigurationXMLfileasfollows.
<beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:citrus-selenium="http://www.citrusframework.org/schema/selenium/config"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.citrusframework.org/schema/selenium/confighttp://www.citrusframework.org/schema/selenium/config/citrus-selenium-config.xsd">
[...]
</beans>
AfterthatyouareabletousecustomizedCitrusXMLelementsinordertodefinetheSpringbeans.
Seleniumbrowser
CitrusReferenceGuide
435Selenium
![Page 436: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/436.jpg)
Seleniumusesbrowserautomationinordertosimulatetheuserinteractwithwebapplications.YoucanconfiguretheSeleniumbrowserandwebdriverasSpringbean.
<citrus-selenium:browserid="seleniumBrowser"type="firefox"start-page="http://citrusframework.org"/>
TheSeleniumbrowsercomponentsupportsdifferentbrowsertypesforthecommonlyusedbrowsersoutinthewild.
htmlunitfirefoxsafarichromegooglechromeinternetexploreredgecustom
Htmlunitisthedefaultbrowsertypeandrepresentsaheadlessbrowserthatexecutedwithoutdisplayingthegraphicaluserinterface.IncaseyouneedatotallydifferentbrowseroryouneedtocustomizetheSeleniumwebdriveryoucanusethebrowserType="custom"incombinationwithawebdriverreference:
<citrus-selenium:browserid="mySeleniumBrowser"type="custom"web-driver="operaWebDriver"/>
<beanid="operaWebDriver"class="org.openqa.selenium.opera.OperaDriver"/>
NowCitrusisusingthecustomizedSeleniumwebdriverimplementation.
NoteWhenusingFirefoxasbrowseryoumayalsowanttosettheoptionalpropertiesfirefox-profileandversion.
<citrus-selenium:browserid="mySeleniumBrowser"type="firefox"firefox-profile="firefoxProfile"version="FIREFOX_38"start-page="http://citrusframework.org"/>
<beanid="firefoxProfile"class="org.openqa.selenium.firefox.FirefoxProfile"/>
CitrusReferenceGuide
436Selenium
![Page 437: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/437.jpg)
NowCitrusisabletoexecuteSeleniumoperationsasauser.
Seleniumactions
WehaveseveralCitrustestactionseachrepresentingaSeleniumcommand.TheseactionscanbepartofaCitrustestcase.AsaprerequisitewehavetoenabletheSeleniumspecifictestactionsinourXMLtestasfollows:
<beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:selenium="http://www.citrusframework.org/schema/selenium/testcase"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.citrusframework.org/schema/selenium/testcasehttp://www.citrusframework.org/schema/selenium/testcase/citrus-selenium-testcase.xsd"
[...]
</beans>
Weaddedaspecialseleniumnamespacewithprefixselenium:sonowwecanstarttoaddSeleniumtestactionstothetestcase:
XMLDSL
<testcasename="SeleniumCommandIT"><actions><selenium:startbrowser="webBrowser"/>
<selenium:navigatepage="http://localhost:8080"/>
<selenium:find><selenium:elementtag-name="h1"text="Welcome!"><selenium:styles><selenium:stylename="font-size"value="40px"/></selenium:styles></selenium:element></selenium:find>
<selenium:click><selenium:elementid="ok-button"/></selenium:click></actions></testcase>
CitrusReferenceGuide
437Selenium
![Page 438: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/438.jpg)
InthisverysimpleexamplewefirststarttheSeleniumbrowserinstance.AfterthatwecancontinuetouseSeleniumcommandswithoutbrowserattributeexplicitlyset.Citrusknowswhichbrowserinstanceiscurrentlyactiveandwillautomaticallyusethisopenedbrowserinstance.Nextinthisexamplewefindsomeelementonthedisplayedpagebyitstag-nameandtext.Wealsovalidatetheelementstylefont-sizetomeettheexpectedvalue40pxinthisstep.
Inadditiontothattheexampleperformsaclickoperationontheelementwiththeidok-button.Seleniumsupportselementfindoperationsondifferentproperties:
idfindselementbasedontheidattributenamefindselementbasedonthenameattributetag-namefindselementbasedonthetagnameclass-namefindselementbasedonthecssclassnamelink-textfindslinkelementbasedonthelink-textxpathfindselementbasedonXPathevaluationintheDOM
BasedonthatwecanexecuteseveralSeleniumcommandsinatestcaseandvalidatetheresultssuchaswebelements.
CitrussupportsthefollowingSeleniumcommandswithrespectivetestactions:
selenium:startStartthebrowserinstanceselenium:findFindselementoncurrentpageandvalidateselementpropertiesselenium:clickPerformsclickoperationonelementselenium:hoverPerformshoveroperationonelementselenium:navigateNavigatestonewpageurl(includinghistoryback,forwardandrefresh)selenium:set-inputFindsinputelementandsetsvalueselenium:check-inputFindscheckboxelementandsets/unsetsvalueselenium:dropdown-selectFindsdropdownelementandselectssingleormultiplevalue/sselenium:pageInstantiatepageobjectwithdependencyinjectionandexecutepageactionwithverificationselenium:openOpennewwindowselenium:closeClosewindowbygivennameselenium:switchSwitchfocustowindowwithgivennameselenium:wait-untilWaitforelementtobehiddenorvisibleselenium:alertAccesscurrentalertdialog(withactionaccessordismiss)selenium:screenshotMakesscreenshotofcurrentpage
CitrusReferenceGuide
438Selenium
![Page 439: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/439.jpg)
selenium:store-fileStorefiletotemporarybrowserdirectoryselenium:get-stored-fileGetsstoredfilefromtemporarybrowserdirectoryselenium:javascriptExecuteJavascriptcodeinbrowserselenium:clear-cacheClearbrowsercacheandallcookiesselenium:stopStopsthebrowserinstance
UptonowwehaveonlyusedtheCitrusXMLDSL.OfcourseallSeleniumcommandsarealsoavailableinJavaDSLasthenextexampleshows.
JavaDSL
@AutowiredprivateSeleniumBrowserseleniumBrowser;
@CitrusTestpublicvoidseleniumTest()selenium().start(seleniumBrowser);
selenium().navigate("http://localhost:8080");
selenium().find().element(By.id("header"));.tagName("h1").enabled(true).displayed(true).text("Welcome!").style("font-size","40px");
selenium().click().element(By.linkText("ClickMe!"));
NowletshaveacloserlookatthedifferentSeleniumtestactionssupportedinCitrus.
Start/stopbrowser
Youcanstartandstopthebrowserinstancewithatestaction.Thisinstantiatesanewbrowserwindowandprepareseverythingforinteractingwiththewebinterface.
XMLDSL
<selenium:startbrowser="seleniumBrowser"/>
<!--Dosomethinginbrowser-->
<selenium:stopbrowser="seleniumBrowser"/>
CitrusReferenceGuide
439Selenium
![Page 440: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/440.jpg)
JavaDSL
selenium().start(seleniumBrowser);
//dosomethinginbrowser
selenium().stop(seleniumBrowser);
AfterstartingabrowserinstanceCitruswillautomaticallyusethisverysamebrowserinstanceinallfurtherSeleniumactions.Thismechanismisbasedonatestvariable(selenium_browser)thatisautomaticallyset.Allothertestactionsareabletoloadthecurrentbrowserinstancebyreadingthistestvariablebeforeexecution.IncaseyouneedtoexplicitlyuseadifferentbrowserinstancethantheactiveinstanceyoucanaddthebrowserattributetoallSeleniumtestactions.
Note
Itisagoodideatostartandstopthebrowserinstancebeforeeachtestcase.Thismakessurethattestsarealsoexecutableinsinglerunanditalwayssetsupanewbrowserinstancesotestswillnotinfluenceeachother.
Find
Thefindelementtestactionsearchesforanelementonthecurrentpage.Theelementisspecifiedbyoneofthefollowingsettings:
idfindselementbasedontheidattributenamefindselementbasedonthenameattributetag-namefindselementbasedonthetagnameclass-namefindselementbasedonthecssclassnamelink-textfindslinkelementbasedonthelink-textxpathfindselementbasedonXPathevaluationintheDOM
Thefindelementactionwillautomaticallyfailincasethereisnosuchelementonthecurrentpage.Incasetheelementisfoundyoucanaddadditionalattributesandpropertiesforfurtherelementvalidation:
XMLDSL
<selenium:find><selenium:elementtag-name="h1"text="Welcome!"><selenium:styles><selenium:stylename="font-size"value="40px"/>
CitrusReferenceGuide
440Selenium
![Page 441: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/441.jpg)
</selenium:styles></selenium:element></selenium:find>
<selenium:find><selenium:elementid="ok-button"text="Ok"enabled="true"displayed="true"><selenium:attributes><selenium:attributename="type"value="submit"/></selenium:attributes></selenium:element></selenium:find>
JavaDSL
selenium().find().element(By.tagName("h1")).text("Welcome!").style("font-size","40px");
selenium().find().element(By.id("ok-button")).tagName("button").enabled(true).displayed(true).text("Ok").style("color","red").attribute("type","submit");
Theexampleabovefindstheh1elementbyitstagnameandvalidatesthetextandcssstyleattributes.Secondlytheok-buttonisvalidatedwithexpectedenabled,displayed,text,styleandattributevalues.Theelementsmustbepresentonthecurrentpageandallexpectedelementpropertieshavetomatch.Otherwisethetestactionandthetestcaseisfailingwithvalidationerrors.
Click
Theactionperformsaclickoperationontheelement.
XMLDSL
<selenium:click><selenium:elementlink-text="ClickMe!"/></selenium:click>
JavaDSL
CitrusReferenceGuide
441Selenium
![Page 442: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/442.jpg)
selenium().click().element(By.linkText("ClickMe!"));
Hover
Theactionperformsahoveroperationontheelement.
XMLDSL
<selenium:hover><selenium:elementlink-text="FindMe!"/></selenium:hover>
JavaDSL
selenium().hover().element(By.linkText("FindMe!"));
Forminputactions
Thefollowingactionsareusedtoaccessforminputelementssuchastextfields,checkboxesanddropdownlists.
XMLDSL
<selenium:set-inputvalue="Citrus"><selenium:elementname="username"/></selenium:set-input>
<selenium:check-inputchecked="true"><selenium:elementxpath="//input[@type='checkbox']"/></selenium:check-input>
<selenium:dropdown-selectoption="happy"><selenium:elementid="user-mood"/></selenium:dropdown-select>
JavaDSL
selenium().setInput("Citrus").element(By.name("username"));selenium().checkInput(true).element(By.xpath("//input[@type='checkbox']"));
selenium().select("happy").element(By.id("user-mood"));
CitrusReferenceGuide
442Selenium
![Page 443: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/443.jpg)
Theactionsaboveselectdropdownoptionsandsetuserinputontextfieldsandcheckboxes.Asusualtheformelementsareselectedbysomepropertiessuchasids,namesorxpathexpressions.
Pageactions
PageobjectsareawellknownpatternwhenusingSelenium.Thepageobjectsdefineelementsthatthepageisworkingwith.Inadditiontothatthepageobjectsdefineactionsthatcanbeexecutedfromoutside.Thisobjectorientedapproachforaccessingpagesandtheirelementsisaverygoodidea.Letshavealookatasamplepageobject.
publicclassUserFormPageimplementsWebPage
@FindBy(id="userForm")privateWebElementform;
@FindBy(id="username")privateWebElementuserName;
/***Setstheusername.*/publicvoidsetUserName(Stringvalue,TestContextcontext)userName.clear();userName.sendKeys(value);
/***Submitstheform.*@paramcontext*/publicvoidsubmit(TestContextcontext)form.submit();
AsyoucanseethepageobjectisaJavaPOJOthatimplementstheWebPageinterface.ThepagedefinesWebElementmembers.TheseareautomaticallyinjectedbyCitrusandSeleniumbasedontheFindByannotation.NowthetestcaseisabletoloadthatpageobjectandexecutesomeactionmethodsonthepagesuchassetUserNameorsubmit.
XMLDSL
<selenium:pagetype="com.consol.citrus.selenium.pages.UserFormPage"
CitrusReferenceGuide
443Selenium
![Page 444: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/444.jpg)
action="setUserName"><selenium:arguments><selenium:argument>Citrus</selenium:argument></selenium:arguments></selenium:page>
<selenium:pagetype="com.consol.citrus.selenium.pages.UserFormPage"action="submit"/>
JavaDSL
selenium().page(UserFormPage.class).argument("Citrus").execute("setUserName");
selenium().page(UserFormPage.class).execute("submit");
ThepageobjectclassisautomaticallyloadedandinstantiatedwithdependencyinjectionforallFindByannotatedwebelements.Afterthattheactionmethodisexecuted.TheactionmethodscanalsohavemethodparametersasseeninsetUserName.Thevalueparameterisautomaticallysetwhencallingthemethod.
MethodscanalsousetheoptionalparameterTestContext.Withthiscontextyoucanaccessthecurrenttestcontextwithalltestvariablesforinstance.Thismethodparametershouldalwaysbethelastparameter.
Pagevalidation
Wecanalsousepageobjectforvalidationpurpose.Thepageobjectisloadedandinstantiatedasdescribedinprevioussection.Thenthepagevalidatoriscalled.Thevalidatorperformsassertionsandvalidationoperationswiththepageobject.Letsseeasamplepagevalidator:
publicclassUserFormValidatorimplementsPageValidator<UserFormPage>
@Overridepublicvoidvalidate(UserFormPagewebPage,SeleniumBrowserbrowser,TestContextcontext)Assert.isTrue(webPage.getUserName()!=null);Assert.isTrue(StringUtils.hasText(webPage.getUserName().getAttribute("value")));
CitrusReferenceGuide
444Selenium
![Page 445: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/445.jpg)
Thepagevalidatoriscalledwiththewebpageinstance,thebrowserandthetestcontext.Thevalidatorshouldassertpageobjectsandwebelementsforvalidationpurpose.Inatestcasewecancallthevalidatortovalidatethepage.
XMLDSL
<beanid="userFormValidator"class="com.consol.citrus.selenium.pages.UserFormValidator"/>
<selenium:pagetype="com.consol.citrus.selenium.pages.UserFormPage"action="validate"validator="userFormValidator"/>
JavaDSL
@AutowiredprivateUserFormValidatoruserFormValidator;
selenium().page(UserFormPage.class).execute("validate").validator(userFormValidator);
Insteadofusingaseparatevalidatorclassyoucanalsoputthevalidationmethodtothepageobjectitself.Thenpageobjectandvalidationisdonewithinthesameclass:
publicclassUserFormPageimplementsWebPage,PageValidator<UserFormPage>
@FindBy(id="userForm")privateWebElementform;
@FindBy(id="username")privateWebElementuserName;
/***Setstheusername.*/publicvoidsetUserName(Stringvalue,TestContextcontext)userName.clear();userName.sendKeys(value);
/***Submitstheform.*@paramcontext*/publicvoidsubmit(TestContextcontext)form.submit();
@Override
CitrusReferenceGuide
445Selenium
![Page 446: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/446.jpg)
publicvoidvalidate(UserFormPagewebPage,SeleniumBrowserbrowser,TestContextcontext)Assert.isTrue(userName!=null);Assert.isTrue(StringUtils.hasText(userName.getAttribute("value")));Assert.isTrue(form!=null);
XMLDSL
<selenium:pagetype="com.consol.citrus.selenium.pages.UserFormPage"action="validate"/>
JavaDSL
selenium().page(UserFormPage.class).execute("validate");
Wait
Sometimesitisrequiredtowaitforanelementtoappearordisappearonthecurrentpage.Thewaitactionwillwaitagiventimefortheelementstatustobevisibleorhidden.
XMLDSL
<selenium:waituntil="hidden"><selenium:elementid="info-dialog"/></selenium:wait>
JavaDSL
selenium().waitUntil().hidden().element(By.id("info-dialog"));
Theexamplewaitsfortheelementinfo-dialogtodisappear.Thetimetowaitis5000millisecondsbydefault.Youcansetthetimeoutontheaction.DuetoSeleniumlimitationstheminimumwaittimeis1000milliseconds.
Navigate
TheactionnavigatestoanewpageeitherbyusinganewrelativepathoracompletenewHttpURL.
CitrusReferenceGuide
446Selenium
![Page 447: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/447.jpg)
XMLDSL
<selenium:navigatepage="http://localhost:8080"/>
<selenium:navigatepage="help"/>
JavaDSL
selenium().navigate("http://localhost:8080");
selenium().navigate("help");
ThesampleabovedescribesanewpagewithnewHttpURL.Thebrowserwillnavigatetothisnewpage.AllfurtherSeleniumactionsareperformedonthisnewpage.ThesecondnavigationactionopenstherelativepagehelpsothenewpageURLishttp://localhost:8080/help.
Navigationisalwaysdoneontheactivebrowserwindow.Youcanmanagetheopenedwindowsasdescribedinnextsection.
Windowactions
Seleniumisabletomanagemultiplewindows.Soyoucanopen,closeandswichactivewindowsinaCitrustest.
XMLDSL
<selenium:open-windowname="my_window"/><selenium:switch-windowname="my_window"/><selenium:close-windowname="my_window"/>
JavaDSL
selenium().open().window("my_window");selenium().focus().window("my_window");selenium().close().window("my_window");
WhenanewwindowisopenedSeleniumcreatesawindowhandleforus.Thiswindowhandleissavedastestvariableusingagivenwindowname.Soafteropeningthewindowyoucanaccessthewindowbyitsnameinfurtheractions.Allupcoming
CitrusReferenceGuide
447Selenium
![Page 448: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/448.jpg)
Seleniumactionswilltakeplaceinthisnewactivewindow.Ofcoursethetestactionswillfailassoonasthewindowwiththatgivennameismissing.Citrususesdefaultwindownamesthatareautomaticallyusedastestvariables:
selenium_active_windowtheactivewindowhandleselenium_last_windowthelastwindowhandlewhenswitchedtootherwindow
Alert
Weareabletoaccessthealertdialogonthecurrentpage.Citruswillvalidatethedisplayeddialogtextandacceptordismissofthedialog.
XMLDSL
<selenium:alertaccept="true"><selenium:alert-text>Hello!</selenium:alert-text></selenium:alert>
JavaDSL
selenium().alert().text("Hello!").accept();
Thealertdialogtextisvalidatedwhenexpectedtextisgivenonthetestaction.Theusercandecidetoacceptordismissthedialog.Afterthatthedialogshouldbeclosed.Incasethetestactionfailstofindanopenalertdialogthetestactionraisesruntimeerrorsandthetestwillfail.
Makescreenshot
Youcanexecutethisactionincaseyouwanttotakeascreenshotofthecurrentpage.Thisactiononlyworkswithbrowsersthatactuallydisplaytheuserinterface.TheactionwillnothaveanyeffectwhenexecutedwithHtmlunitwebdriverinheadlessmode.
XMLDSL
<selenium:screenshot/>
<selenium:screenshotoutput-dir="target"/>
JavaDSL
CitrusReferenceGuide
448Selenium
![Page 449: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/449.jpg)
selenium().screenhsot();
selenium().screenhsot("target");
Thetestactionhasanoptionalparameteroutput-dirwhichrepresentstheoutputdirectorywherethescreenshotissavedto.
Temporarystorage(Firefox)
ImportantThisactiononlyworkswithFirefoxwebdriver!Otherbrowsersarenotworkingwiththetemporarydownloadstorage.
Thebrowserusesatemporarystoragefordownloadedfiles.Wecanaccessthistemporarystorageduringatestcase.
XMLDSL
<selenium:store-filefile-path="classpath:download/file.txt"/><selenium:get-stored-filefile-name="file.txt"/>
JavaDSL
selenium().store("classpath:download/file.txt");selenium().getStored("file.txt");
Asyoucanseethetestcaseisabletostorenewfilestothetemporarybrowserstorage.Wehavetogivethefilepathasclasspathorfilesystempath.Whenreadingthetemporaryfilestorageweneedtospecifythefilenamethatwewanttoaccessinthetemporarystorage.Thetemporarystorageisnotcapableofsubdirectoriesallfilesarestoreddirectlytothestorageinonesingledirectory.
Incasethestoredfileisnotfoundbythatnamethetestactionfailswithrespectiveerrors.OntheotherhandwhenthefileisfoundintemporarystorageCitruswillautomaticallycreateanewtestvariableselenium_download_filewhichcontainsthefilenameasvalue.
Clearbrowsercache
Whenclearingthebrowsercacheallcookiesandtemporaryfileswillbedeleted.
XMLDSL
CitrusReferenceGuide
449Selenium
![Page 450: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/450.jpg)
<selenium:clear-cache/>
JavaDSL
selenium().clearCache();
CitrusReferenceGuide
450Selenium
![Page 451: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/451.jpg)
DynamicendpointcomponentsEndpointsrepresentthecentralcomponentsinCitrustosendorreceiveamessageonsomedestination.UsuallyendpointsgetdefinedinthebasicCitrusSpringapplicationcontextconfigurationasSpringbeancomponents.Insomecasesthismightbeoverengineeringasthetesterjustwantstosendorreceiveamessage.Inparticularthisisdonewhendoingsanitychecksinserverendpointswhiledebuggingacertainscenario.
WithendpointcomponentsyouareabletocreatetheCitrusendpointforsendingandreceivingamessageattestruntime.ThereisnoadditionalconfigurationorSpringbeancomponentneeded.YoujustusetheendpointuriinaspecialnamingconventionandCitruswillcreatetheendpointforyou.Letusseeafirstexampleofthisscenario:
<testcasename="DynamicEndpointTest"><actions><sendendpoint="jms:Hello.Queue?timeout=10000"><message><payload>[...]</payload></message></send>
<receiveendpoint="jms:Hello.Response.Queue?timeout=5000"><message><payload>[...]</payload></message></receive></actions></testcase>
Asyoucanseetheendpointurijustgoesintothetestcaseactioninsubstitutiontotheusualendpointreferencename.InsteadofreferencingabeanidthatpointstothepreviouslyconfiguredCitrusendpointweusetheendpointuridirectly.Theendpointurishouldgiveallinformationtocreatetheendpointatruntime.Intheexampleaboveweuseakeywordjms:whichtellsCitrusthatweneedtocreateaJMSmessageendpoint.SecondlywegivetheJMSdestinationnameHello.Queuewhichisamandatorypartof
CitrusReferenceGuide
451Endpointcomponent
![Page 452: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/452.jpg)
theendpointuriwhenusingtheJMScomponent.Theoptionaltimeoutparametercompletedtheuri.CitrusisabletocreatetheJMSendpointatruntimesendingthemessagetothedefineddestinationviaJMS.
OfcoursethismechanismisnotlimitedtoJMSendpoints.WecanusealldefaultCitrusmessagetransportsintheendpointuri.Justpicktherightkeywordthatdefinesthemessagetransporttouse.Hereisalistofsupportedkeywords:
jms:CreatesaJMSendpointforsendingandreceivingmessagetoaqueueortopicchannel:CreatesachannelendpointforsendingandreceivingmessagesusinganinmemorySpringIntegrationmessagechannelhttp:CreatesaHTTPclientforsendingarequesttosomeserverURLsynchronouslywaitingfortheresponsemessagews:CreatesaWebSocketclientforsendingmessagestoorreceivingmessagesfromaWebSocketserversoap:CreatesaSOAPWebServiceclientthatsendaproperSOAPmessagetotheserverURLandwaitsforthesynchronousresponsetoarrivessh:Createsanewsshclientforpublishingacommandtotheservermail:orsmtp:CreatesanewmailclientforsendingamailmimemessagetoaSMTPservercamel:CreatesanewApacheCamelendpointforsendingandreceivingCamelexchangesbothtoandfromCamelroutes.vertx:oreventbus:CreatesanewVert.xinstancesendingandreceivingmessageswiththenetworkeventbusrmi:CreatesanewRMIclientinstancesendingandreceivingmessagesformethodinvocationonremoteinterfacesjmx:CreatesanewJMXclientinstancesendingandreceivingmessagestoandfromamanagedbeanserver.
Dependingonthemessagetransportwehavetoaddmandatoryparameterstotheendpointuri.IntheJMSexamplewehadtospecifythedestinationname.Themandatoryparametersarealwayspartoftheendpointuri.Optionalparameterscanbeaddedaskeyvaluepairstotheendpointuri.Theavailableparametersdependontheendpointkeywordthatyouhavechosen.Seetheseexampleendpointuriexpressions:
jms:queuename?connectionFactory=specialConnectionFactory&timeout=10000jms:topic:topicname?connectionFactory=topicConnectionFactoryjms:sync:queuename?connectionFactory=specialConnectionFactory&pollingInterval=100&replyDestination=myReplyDestination
channel:channelName
CitrusReferenceGuide
452Endpointcomponent
![Page 453: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/453.jpg)
channel:sync:channelNamechannel:channelName?timeout=10000&channelResolver=myChannelResolver
http:localhost:8088/testhttp://localhost:8088/testhttp:localhost:8088?requestMethod=GET&timeout=10000&errorHandlingStrategy=throwsException&requestFactory=myRequestFactoryhttp://localhost:8088/test?requestMethod=DELETE&customParam=foo
websocket:localhost:8088/testwebsocket://localhost:8088/testws:localhost:8088/testws://localhost:8088/test
soap:localhost:8088/testsoap:localhost:8088?timeout=10000&errorHandlingStrategy=propagateError&messageFactory=myMessageFactory
mail:localhost:25000smtp://localhost:25000smtp://localhost?timeout=10000&username=foo&password=1234&mailMessageMapper=myMapper
ssh:localhost:2200ssh://localhost:2200?timeout=10000&strictHostChecking=true&user=foo&password=12345678
rmi://localhost:1099/someServicermi:localhost/someService&timeout=10000
jmx:rmi:///jndi/rmi://localhost:1099/someServicejmx:platform&timeout=10000
camel:direct:addresscamel:seda:addresscamel:jms:queue:someQueue?connectionFactory=myConnectionFactorycamel:activemq:queue:someQueue?concurrentConsumers=5&destination.consumer.prefetchSize=50camel:controlbus:route?routeId=myRoute&action=status
vertx:addressNamevertx:addressName?port=10105&timeout=10000&pubSubDomain=truevertx:addressName?vertxInstanceFactory=vertxFactory
Theoptionalparametersgetdirectlysetasendpointconfiguration.YoucanuseprimitivevaluesaswellasSpringbeanidreferences.CitruswillautomaticallydetectthetargetparametertypeandresolvethevaluetoaSpringbeanintheapplicationcontextifnecessary.IfyouusesomeunknownparameterCitruswillraiseanexceptionatruntimeastheendpointcouldnotbecreatedproperly.
CitrusReferenceGuide
453Endpointcomponent
![Page 454: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/454.jpg)
Insynchronouscommunicationwehavetoreuseendpointcomponentsinordertoreceivesynchronousmessagesonreplydestinations.Thisisaproblemwhenusingdynamicendpointsastheendpointsgetcreatedatruntime.Citrususesacachingofendpointsthatgetcreatedatruntime.Followingfromthatwehavetousetheexactsameendpointuriinyourtestcaseinordertogetthecachedendpointinstance.Withthislittletricksynchronouscommunicationwillworkjustasitisdonewithstaticendpointcomponents.Havealookatthissampletest:
<testcasename="DynamicEndpointTest"><actions><sendendpoint="jms:sync:Hello.Sync.Queue"><message><payload>[...]</payload></message></send>
<receiveendpoint="jms:sync:Hello.Sync.Queue"><message><payload>[...]</payload></message></receive></actions></testcase>
Asyoucanseeweusedtheexactdynamicendpointuriinbothsendandreceiveactions.Citrusisthenabletoreusethesamedynamicendpointandthesynchronousreplywillbereceivedasexpected.Howeverthereuseofexactlythesameendpointurimightgetannoyingaswealsohavetocopyendpointuriparametersandsoon.
<testcasename="DynamicEndpointTest"><actions><sendendpoint="http://localhost:8080/HelloService?user=1234567"><message><payload>[...]</payload></message></send>
<receiveendpoint="http://localhost:8080/HelloService?user=1234567"><message><payload>
CitrusReferenceGuide
454Endpointcomponent
![Page 455: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/455.jpg)
[...]</payload></message></receive></actions></testcase>
Wehavetousetheexactsameendpointuriwhenreceivingthesynchronousserviceresponse.Thisisnotverystraightforward.ThisiswhyCitrusalsosupportsdynamicendpointnames.WithaspecialendpointuriparametercalledendpointNameyoucannamethedynamicendpoint.Inacorrespondingreceiveactionyoujustusetheendpointnameasreferencewhichmakeslifemoreeasy:
<testcasename="DynamicEndpointTest"><actions><sendendpoint="http://localhost:8080/HelloService?endpointName=myHttpClient"><message><payload>[...]</payload></message></send>
<receiveendpoint="http://localhost?endpointName=myHttpClient"><message><payload>[...]</payload></message></receive></actions></testcase>
Sowecanreferencethedynamicendpointwiththegivenname.TheinternalendpointNameuriparameterisautomaticallyremovedbeforesendingoutmessages.OnceagainthedynamicendpointurimechanismprovidesafastwaytowritetestcasesinCitruswithlessconfiguration.ButyoushouldconsidertousethestaticendpointcomponentsdefinedinthebasicSpringbeanapplicationcontextforendpointsthatareheavilyreusedinmultipletestcases.
CitrusReferenceGuide
455Endpointcomponent
![Page 456: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/456.jpg)
EndpointadapterEndpointadapterhelptocustomizethebehaviorofaCitrusserversuchasHTTPorSOAPwebservers.AstheserversgetstartedwiththeCitruscontexttheyarereadytoreceiveincomingclientrequests.Nowtherearedifferentwaystoprocesstheseincomingrequestsandtoprovideaproperresponsemessage.Bydefaulttheserverwillforwardtheincomingrequesttoainmemorymessagechannelwhereatestcanreceivethemessageandprovideasynchronousresponse.Thismessagechannelhandlingisdoneautomaticallybehindthescenessothetesterdoesnotcareaboutthesethings.Thetesterjustusestheserverdirectlyasendpointreferenceinthetestcase.Thisisthedefaultbehaviour.InadditiontothatyoucandefinecustomendpointadaptersontheCitrusserverinordertochangethisdefaultbehavior.
Yousetthecustomendpointadapterdirectlyontheserverconfigurationasfollows:
<citrus-http:serverid="helloHttpServer"port="8080"auto-start="true"endpoint-adapter="emptyResponseEndpointAdapter"resource-base="src/it/resources"/>
<citrus:empty-response-adapterid="emptyResponseEndpointAdapter"/>
Nowletushaveacloserlookattheprovidedendpointadapterimplementations.
Emptyresponseendpointadapter
Thisisthesimplestendpointadapteryoucanthinkof.ItsimplyprovidesanemptysuccessresponseusingtheHTTPresponsecode200.TheadapterdoesnotneedanyconfigurationsorpropertiesasitsimplyrespondswithanemptyHTTPresponse.
<citrus:empty-response-adapterid="emptyResponseEndpointAdapter"/>
Staticresponseendpointadapter
Thenextmorecomplexendpointadapterwillalwaysreturnastaticresponsemessage.
<citrus:static-response-adapterid="endpointAdapter"><citrus:payload>
CitrusReferenceGuide
456Endpointadapter
![Page 457: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/457.jpg)
<![CDATA[<HelloResponsexmlns="http://www.consol.de/schemas/samples/sayHello.xsd"><MessageId>123456789</MessageId><CorrelationId>Cx1x123456789</CorrelationId><Text>HelloUser</Text></HelloResponse>]]></citrus:payload><citrus:header><citrus:elementname="http://www.consol.de/schemas/samplesh1:Operation"value="sayHello"/><citrus:elementname="http://www.consol.de/schemas/samplesh1:MessageId"value="123456789"/></citrus:header></citrus:static-response-adapter>
Theendpointadapterisconfiguredwithastaticmessagepayloadandstaticresponseheadervalues.Theresponsetotheclientisthereforealwaysthesame.YoucanadddynamicvaluesbyusingCitrusfunctionssuchasrandomStringorrandomNumber.Alsoweareabletousevaluesoftheactualrequestmessagethathastriggeredtheresponseadapter.Therequestisavailableviathelocalmessagestore.IncombinationwithXpathorJsonPathfunctionswecanmapvaluesfromtheactualrequest.
<citrus:static-response-adapterid="endpointAdapter"><citrus:payload><![CDATA[<HelloResponsexmlns="http://www.consol.de/schemas/samples/sayHello.xsd"><MessageId>citrus:randomNumber(10)</MessageId><CorrelationId>citrus:xpath(citrus:message(request.payload()),'/hello:HelloRequest/hello:CorrelationId')</CorrelationId><Text>HelloUser</Text></HelloResponse>]]></citrus:payload><citrus:header><citrus:elementname="http://www.consol.de/schemas/samplesh1:Operation"value="sayHello"/><citrus:elementname="http://www.consol.de/schemas/samplesh1:MessageId"value="citrus:randomNumber(10)"/></citrus:header></citrus:static-response-adapter>
CitrusReferenceGuide
457Endpointadapter
![Page 458: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/458.jpg)
TheexampleabovemapstheCorrelationIdoftheHelloRequestmessagetotheresponsewithXpathfunction.Thelocalmessagestoreautomaticallyhasthemessagenamedrequeststoredsowecanaccessthepayloadwiththismessagename.
NoteXMLisnamespacespecificsoweneedtousethenamespaceprefixhellointheXpathexpression.ThenamespaceprefixshouldevaluatetoaglobalnamespaceentryintheglobalCitrusxpath-namespace.
Requestdispatchingendpointadapter
Theideabehindtherequestdispatchingendpointadapteristhattheincomingrequestsaredispatchedtoseveralotherendpointadapters.Thedecisionwhichendpointadaptershouldhandletheactualrequestisdonedependingonsomeadaptermapping.Themappingisdonebasedonthepayloadorheaderdataoftheincomingrequest.Amappingstrategyevaluatesamappingkeyusingtheincomingrequest.YoucanthinkofanXPathexpressionthatevaluatestothemappingkeyforinstance.Theendpointadapterthatmapstothemappingkeyisthencalledtohandletherequest.
Sotherequestdispatchingendpointadapterisabletodynamicallycallseveralotherendpointadaptersbasedontheincomingrequestmessageatruntime.Thisisverypowerful.ThenextexampleusestherequestdispatchingendpointadapterwithaXPathmappingkeyextractor.
<citrus:dispatching-endpoint-adapterid="dispatchingEndpointAdapter"mapping-key-extractor="mappingKeyExtractor"mapping-strategy="mappingStrategy"/>
<beanid="mappingStrategy"class="com.consol.citrus.endpoint.adapter.mapping.SimpleMappingStrategy"><propertyname="adapterMappings"><map><entrykey="sayHello"ref="helloEndpointAdapter"/></map></property></bean>
<beanid="mappingKeyExtractor"class="com.consol.citrus.endpoint.adapter.mapping.XPathPayloadMappingKeyExtractor"><propertyname="xpathExpression"value="//TestMessage/Operation/*"/></bean>
<citrus:static-response-adapterid="helloEndpointAdapter"><citrus:payload><![CDATA[<HelloResponse
CitrusReferenceGuide
458Endpointadapter
![Page 459: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/459.jpg)
xmlns="http://www.consol.de/schemas/samples/sayHello.xsd"><MessageId>123456789</MessageId><Text>HelloUser</Text></HelloResponse>]]></citrus:payload></citrus:static-response-adapter>
TheXPathmappingkeyextractorexpressiondecidesforeachrequestwhichmappingkeytouseinordertofindaproperendpointadapterthroughthemappingstrategy.Theendpointadaptersavailableintheapplicationcontextaremappedviatheirbeanid.Forinstanceanincomingrequestwithamatchingelement//TestMessage/Operation/sayHellowouldbehandledbytheendpointadapterbeanthatisregisteredinthemappingstrategyas"sayHello"key.TheavailableendpointadaptersareconfiguredinthesameSpringapplicationcontext.
Citrusprovidesseveraldefaultmappingkeyextractorimplementations.
HeaderMappingKeyExtractor:Readsaspecialheaderentryandusesitsvalueasmappingkey
SoapActionMappingKeyExtractor:Usesthesoapactionheaderentryasmappingkey
XPathPayloadMappingKeyExtractor:EvaluatesaXPathexpressionontherequestpayloadandusestheresultasmappingkey
Inadditiontothatweneedamappingstrategy.Citrusprovidesfollowingdefaultimplementations.
SimpleMappingStrategy:Simplekeyvaluemapwithendpointadapterreferences
BeanNameMappingStrategy:LoadstheendpointadapterSpringbeanwiththegivenidmatchingthemappingkey
ContextLoadingMappingStrategy:SameasBeanNameMappingStrategybutloadsaseparateapplicationcontextdefinedbyexternalfileresource
Channelendpointadapter
ThechannelconnectingendpointadapteristhedefaultadapterusedinallCitrusservercomponents.Indeedthisadapteralsoprovidesthemostflexibility.Thisadapterforwardsincomingrequeststoachanneldestination.Theadapteriswaitingforaproperresponse
CitrusReferenceGuide
459Endpointadapter
![Page 460: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/460.jpg)
onareplydestinationsynchronously.Withthechannelendpointcomponentsyoucanreadtherequestsonthechannelandprovideaproperresponseonthereplydestination.
<citrus:channel-endpoint-adapterid="channelEndpointAdapter"channel-name="inbound.channel"timeout="2500"/>
JMSendpointadapter
AnotherpowerfulendpointadapteristheJMSconnectingadapterimplementation.ThisadapterforwardsincomingrequeststoaJMSdestinationandwaitsforaproperresponseonareplydestination.AJMSendpointcanaccesstherequestsinternallyandprovideaproperresponseonthereplydestination.Sothisadapterisveryflexibletoprovideproperresponsemessages.
Thisspecialadaptercomeswiththecitrus-jmsmodule.SoyouhavetoaddthemoduleandthespecialXMLnamespaceforthismoduletoyourconfigurationfiles.TheMavenmoduleforcitrus-jmsgoestotheMavenPOMfileasnormalprojectdependency.Thecitrus-jmsnamespacegoestotheSpringbeanXMLconfigurationfileasfollows:
NoteCitrusprovidesa"citrus-jms"configurationnamespaceandschemadefinitionforJMSrelatedcomponentsandfeatures.IncludethisnamespaceintoyourSpringconfigurationinordertousetheCitrusJMSconfigurationelements.ThenamespaceURIandschemalocationareaddedtotheSpringconfigurationXMLfileasfollows.
<beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:citrus-jms="http://www.citrusframework.org/schema/jms/config"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.citrusframework.org/schema/jms/confighttp://www.citrusframework.org/schema/jms/config/citrus-jms-config.xsd">
[...]
</beans>
AfterthatyouareabletousetheadapterimplementationintheSpringbeanconfiguration.
CitrusReferenceGuide
460Endpointadapter
![Page 461: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/461.jpg)
<citrus-jms:endpoint-adapterid="jmsEndpointAdapter"destination-name="JMS.Queue.Requests.In"reply-destination-name="JMS.Queue.Response.Out"connection-factory="jmsConnectionFactory"timeout="2500"/>
<beanid="jmsConnectionFactory"class="org.apache.activemq.ActiveMQConnectionFactory"><propertyname="brokerURL"value="tcp://localhost:61616"/></bean>
CitrusReferenceGuide
461Endpointadapter
![Page 462: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/462.jpg)
FunctionsThetestframeworkwillofferseveralfunctionsthatareusefulthroughoutthetestexecution.Thefunctionswillalwaysreturnastringvaluethatisreadyforuseasvariablevalueordirectlyinsideatextmessage.
Asetoffunctionsisusuallycombinedtoafunctionlibrary.Thelibraryhasaprefixthatwillidentifythefunctionsinsidethetestcase.Thedefaulttestframeworkfunctionlibraryusesadefaultprefix(citrus).Youcanwriteyourownfunctionlibraryusingyourownprefixinordertoextendthetestframeworkfunctionalitywheneveryouwant.
ThelibraryisbuiltintheSpringconfigurationandcontainsasetoffunctionsthatareofpublicuse.
<citrus:function-libraryid="testLibrary"prefix="foo:"><citrus:functionname="randomNumber">class="com.consol.citrus.functions.RandomNumberFunction"/><citrus:functionname="randomString">class="com.consol.citrus.functions.RandomStringFunction"/><citrus:functionname="customFunction">ref="customFunctionBean"/>...</citrus:function-library>
AsyoucanseethelibrarydefinesonetomanyfunctionseitherreferencedasnormalSpringbeanorbyitsimplementingJavaclassname.Citrusconstructsthelibraryandyouareabletousethefunctionsinyourtestcasewiththeleadinglibraryprefixjustlikethis:
foo:randomNumber()foo:randomString()foo:customFunction()
TipYoucanaddcustomfunctionimplementationsandcustomfunctionlibraries.Justuseacustomprefixforyourlibrary.ThedefaultCitrusfunctionlibraryusesthecitrus:prefix.Inthenextchaptersthedefaultfunctionsofferedbytheframeworkwillbedescribedindetail.
concat()
CitrusReferenceGuide
462Functions
![Page 463: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/463.jpg)
Thefunctionwillcombineseveralstringtokenstoasinglestringvalue.Thismeansthatyoucancombineastatictextvaluewithavariablevalueforinstance.Afirstexampleshouldclarifytheusage:
<testcasename="concatFunctionTest"><variables><variablename="date"value="citrus:currentDate(yyyy-MM-dd)"/><variablename="text"value="HelloTestFramework!"/></variables><actions><echo><message>citrus:concat('Todayis:',$date,'right!?')</message></echo><echo><message>citrus:concat('Textis:',$text)</message></echo></actions></testcase>
Pleasedonotforgettomarkstatictextwithsinglequotesigns.Thereisnolimitationforstringtokenstobecombined.
citrus:concat('Text1','Text2','Text3',$text,'Text5',…,'TextN')
Thefunctioncanbeusedwherevervariablescanbeused.ForinstancewhenvalidatingXMLelementsinthereceiveaction.
<message><validatepath="//element/element"value="citrus:concat('Cx1x',$generatedId)"/></message>
substring()
Thefunctionwillhavethreeparameters.
1. Stringtoworkon2. Startingindex3. Endindex(optional)
Letushavealookatasimpleexampleforthisfunction:
CitrusReferenceGuide
463Functions
![Page 464: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/464.jpg)
<echo><message>citrus:substring('HelloTestFramework',6)</message></echo><echo><message>citrus:substring('HelloTestFramework',0,5)</message></echo>
Functionoutput:
TestFrameworkHello
stringLength()
Thefunctionwillcalculatethenumberofcharactersinastringrepresentationandreturnthenumber.
<echo><message>citrus:stringLength('HelloTestFramework')</message></echo>
Functionoutput:
20
translate()
Thisfunctionwillreplaceregularexpressionmatchingvaluesinsideastringrepresentationwithaspecifiedreplacementstring.
<echo><message>citrus:translate('H.lloTestFr.mework','\.','a')</message></echo>
Notethatthesecondparameterwillbearegularexpression.Thethirdparameterwillbeasimplereplacementstringvalue.
CitrusReferenceGuide
464Functions
![Page 465: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/465.jpg)
Functionoutput:
HelloTestFramework
substringBefore()
Thefunctionwillsearchforthefirstoccurrenceofaspecifiedstringandwillreturnthesubstringbeforethatoccurrence.Letushaveacloserlookinasimpleexample:
<echo><message>citrus:substringBefore('Test/Framework','/')</message></echo>
Inthespecificexamplethefunctionwillsearchforthe‘/’characterandreturnthestringbeforethatindex.
Functionoutput:
Test
substringAfter()
Thefunctionwillsearchforthefirstoccurrenceofaspecifiedstringandwillreturnthesubstringafterthatoccurrence.Letusclarifythiswithasimpleexample:
<echo><message>citrus:substringAfter('Test/Framework','/')</message></echo>
SimilartothesubstringBeforefunctionthe‘/’characterisfoundinthestring.Butnowtheremainingstringisreturnedbythefunctionmeaningthesubstringafterthischaracterindex.
Functionoutput:
Framework
round()
CitrusReferenceGuide
465Functions
![Page 466: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/466.jpg)
Thisisasimplemathematicfunctionthatwillrounddecimalnumbersrepresentationstotheirnearestnondecimalnumber.
<echo><message>citrus:round('3.14')</message></echo>
Functionoutput:
3
floor()
Thisfunctionwillrounddowndecimalnumbervalues.
<echo><message>citrus:floor('3.14')</message></echo>
Functionoutput:
3.0
ceiling()
Similartofloorfunction,butnowthefunctionwillroundupthedecimalnumbervalues.
<echo><message>citrus:ceiling('3.14')</message></echo>
Functionoutput:
4.0
randomNumber()
Therandomnumberfunctionwillprovideyoutheopportunitytogeneraterandomnumberstringscontainingpositivenumberletters.ThereisasingularBooleanparameterforthatfunctiondescribingwhetherthegeneratednumbershouldhaveexactlytheamountofdigits.Defaultvalueforthispaddingflagwillbetrue.
CitrusReferenceGuide
466Functions
![Page 467: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/467.jpg)
Nextexamplewillshowthefunctionusage:
<variables><variablename="rndNumber1"value="citrus:randomNumber(10)"/><variablename="rndNumber2"value="citrus:randomNumber(10,true)"/><variablename="rndNumber2"value="citrus:randomNumber(10,false)"/><variablename="rndNumber3"value="citrus:randomNumber(3,false)"/></variables>
Functionoutput:
89546387655003485980638765065
randomString()
Thisfunctionwillgeneratearandomstringrepresentationwithadefinedlength.Asecondparameterforthisfunctionwilldefinethecaseofthegeneratedletters(UPPERCASE,LOWERCASE,MIXED).Thelastparameterallowsalsodigitcharactersinthegeneratedstring.Bydefaultdigitcharatersarenotallowed.
<variables><variablename="rndString0"value="$citrus:randomString(10)"/><variablename="rndString1"value="citrus:randomString(10)"/><variablename="rndString2"value="citrus:randomString(10,UPPERCASE)"/><variablename="rndString3"value="citrus:randomString(10,LOWERCASE)"/><variablename="rndString4"value="citrus:randomString(10,MIXED)"/><variablename="rndString4"value="citrus:randomString(10,MIXED,true)"/></variables>
Functionoutput:
HrGHOdfAerAgSSwedetGJSDFUTTRKUdtkhirtsuzVt567JkA32
randomEnumValue()
CitrusReferenceGuide
467Functions
![Page 468: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/468.jpg)
Thisfunctionreturnsoneofitssuppliedarguments.Furthermoreyoucanspecifyacustomfunctionwithaconfiguredlistofvalues(theenumeration).Thefunctionwillrandomlyreturnanentrywhencalledwithoutarguments.Thispromotescodereuseandfacilitatesrefactoring.
InthenextsamplethefunctionisusedtosetahttpStatusCodevariabletooneofthegivenHTTPstatuscodes(200,401,500)
<variablename="httpStatusCode"value="citrus:randomEnumValue('200','401','500')"/>
Asmentionedbeforeyoucandefineacustomfunctionforyourveryspecificneedsinordertoeasilymanagealistofpredefinedvalueslikethis:
<citrus:function-libraryid="myCustomFunctionLibrary"prefix="custom:"><citrus-functionname="randomHttpStatusCode"ref="randomHttpStatusCodeFunction"/></citrus:function-library>
<beanid="randomHttpStatusCodeFunction"class="com.consol.citrus.functions.core.RandomEnumValueFunction"<propertyname="values"><list><value>200</value><value>500</value><value>401</value></list></property></bean>
Wehaveaddedacustomfunctionlibrarywithacustomfunctiondefinition.Thecustomfunction"randomHttpStatusCode"randomlychoosesanHTTPstatuscodeeachtimeitiscalled.Insidethetestyoucanusethefunctionlikethis:
<variablename="httpStatusCode"value="custom:randomHttpStatusCode()"/>
currentDate()
Thisfunctionwilldefinitelyhelpyouwhenaccessingthecurrentdate.Someexampleswillshowtheusageindetail:
<echo><message>citrus:currentDate()</message></echo><echo><message>citrus:currentDate('yyyy-MM-dd')</message></echo><echo><message>citrus:currentDate('yyyy-MM-ddHH:mm:ss')</message></echo>
CitrusReferenceGuide
468Functions
![Page 469: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/469.jpg)
<echo><message>citrus:currentDate('yyyy-MM-dd'T'hh:mm:ss')</message></echo><echo><message>citrus:currentDate('yyyy-MM-ddHH:mm:ss','+1y')</message></echo><echo><message>citrus:currentDate('yyyy-MM-ddHH:mm:ss','+1M')</message></echo><echo><message>citrus:currentDate('yyyy-MM-ddHH:mm:ss','+1d')</message></echo><echo><message>citrus:currentDate('yyyy-MM-ddHH:mm:ss','+1h')</message></echo><echo><message>citrus:currentDate('yyyy-MM-ddHH:mm:ss','+1m')</message></echo><echo><message>citrus:currentDate('yyyy-MM-ddHH:mm:ss','+1s')</message></echo><echo><message>citrus:currentDate('yyyy-MM-ddHH:mm:ss','-1y')</message></echo>
NotethatthecurrentDatefunctionprovidestwoparameters.Firstparameterdescribesthedateformatstring.Thesecondwilldefineadateoffsetstringcontainingyear,month,days,hours,minutesorsecondsthatwillbeaddedorsubtractedtoorfromtheactualdatevalue.
Functionoutput:
01.09.20092009-09-012009-09-0112:00:002009-09-01T12:00:00
upperCase()
Thisfunctionconvertsanystringtouppercaseletters.
<echo><message>citrus:upperCase('HelloTestFramework')</message></echo>
Functionoutput:
HELLOTESTFRAMEWORK
lowerCase()
Thisfunctionconvertsanystringtolowercaseletters.
<echo><message>citrus:lowerCase('HelloTestFramework')</message></echo>
Functionoutput:
CitrusReferenceGuide
469Functions
![Page 470: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/470.jpg)
hellotestframework
average()
Thefunctionwillsumupallspecifiednumbervaluesanddividetheresultthroughthenumberofvalues.
<variablename="avg"value="citrus:average('3','4','5')"/>
avg=4.0
minimum()
Thisfunctionreturnstheminimumvalueinasetofnumbervalues.
<variablename="min"value="citrus:minimum('3','4','5')"/>
min=3.0
maximum()
Thisfunctionreturnsthemaximumvalueinasetofnumbervalues.
<variablename="max"value="citrus:maximum('3','4','5')"/>
max=5.0
sum()
Thefunctionwillsumupallnumbervalues.Thenumbervaluescanalsobenegative.
<variablename="sum"value="citrus:sum('3','4','5')"/>
sum=12.0
absolute()
Thefunctionwillreturntheabsolutenumbervalue.
CitrusReferenceGuide
470Functions
![Page 471: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/471.jpg)
<variablename="abs"value="citrus:absolute('-3')"/>
abs=3.0
mapValue()
Thisfunctionimplementationmapsstringkeystostringvalues.Thisisveryhelpfulwhentheusedkeyisrandomlychosenatruntimeandthecorrespondingvalueisnotdefinedduringthedesigntime.
ThefollowingfunctionlibrarydefinesacustomfunctionformappingHTTPstatuscodestothecorrespondingmessages:
<citrus:function-libraryid="myCustomFunctionLibrary"prefix="custom:"><citrus-functionname="getHttpStatusMessage"ref="getHttpStatusMessageFunction"/></citrus:function-library>
<beanid="getHttpStatusMessageFunction"class="com.consol.citrus.functions.core.MapValueFunction"<propertyname="values"><map><entrykey="200"value="OK"/><entrykey="401"value="Unauthorized"/><entrykey="500"value="InternalServerError"/></map></property></bean>
InthisexamplethefunctionsetsthevariablehttpStatusMessagetothe'InternalServerError'stringdynamicallyatruntime.ThetestonlyknowstheHTTPstatuscodeanddoesnotcareaboutspellingandmessagelocales.
<variablename="httpStatusCodeMessage"value="custom:getHttpStatusMessage('500')"/>
randomUUID()
ThefunctionwillgeneratearandomJavaUUID.
<variablename="uuid"value="citrus:randomUUID()"/>
uuid=98fbd7b0-832e-4b85-b9d2-e0113ee88356
CitrusReferenceGuide
471Functions
![Page 472: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/472.jpg)
encodeBase64()
Thefunctionwillencodeastringtobinarydatausingbase64hexadecimalencoding.
<variablename="encoded"value="citrus:encodeBase64('HalloTestframework')"/>
encoded=VGVzdCBGcmFtZXdvcms=
decodeBase64()
Thefunctionwilldecodebinarydatatoacharactersequenceusingbase64hexadecimaldecoding.
<variablename="decoded"value="citrus:decodeBase64('VGVzdCBGcmFtZXdvcms=')"/>
decoded=HalloTestframework
escapeXml()
IfyouwanttodealwithescapedXMLinyourtestcaseyoumaywanttousethisfunction.ItautomaticallyescapesallXMLspecialcharacters.
<echo><message><![CDATA[citrus:escapeXml('<Message>HalloTestFramework</Message>')]]></message></echo>
<Message>HalloTestFramework</Message>
cdataSection()
UsuallyweuseCDATAsectionstodefinemessagepayloaddatainsideatestcase.WemightrunintoproblemswhenthepayloaditselfcontainsCDATAsectionsasnestedCDATAsectionsareprohibitedbyXMLnature.Inthiscasethenextfunctionshipsveryusefull.
CitrusReferenceGuide
472Functions
![Page 473: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/473.jpg)
<variablename="cdata"value="citrus:cdataSection('payload')"/>
cdata=<![CDATA[payload]]>
digestAuthHeader()
Digestauthenticationisacommonlyusedsecurityalgorithm,especiallyinHttpcommunicationandSOAPWebServices.CitrusoffersafunctiontogenerateadigestauthenticationprincipleusedintheHttpheadersectionofamessage.
<variablename="digest"value="citrus:digestAuthHeader('username','password','authRealm','acegi','POST','http://127.0.0.1:8080','citrus','md5')"/>
Apossibledigestauthenticationheadervaluelookslikethis:
<Digestusername=foo,realm=arealm,nonce=MTMzNT,uri=http://127.0.0.1:8080,response=51f98c,opaque=b29a30,algorithm=md5>
YoucanusethesedigestheadersinmessagessentbyCitruslikethis:
<header><elementname="citrus_http_Authorization"value="vflig:digestAuthHeader('$username','$password','$authRealm','$nonceKey','POST','$uri','$opaque','$algorithm')"/></header>
ThiswillsetaHttpAuthorizationheaderwiththerespectivedigestintherequestmessage.Soyourtestisreadyforclientdigestauthentication.
localHostAddress()
Testcasesmayusethelocalhostaddressforsomereason(e.g.usedasauthenticationprinciple).Asthetestsmayrunondifferentmachinesatthesametimewecannotusestatichostaddresses.TheprovidedfunctionlocalHostAddress()readsthelocalhostnamedynamicallyatruntime.
<variablename="address"value="citrus:localHostAddress()"/>
CitrusReferenceGuide
473Functions
![Page 474: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/474.jpg)
ApossiblevalueiseitherthehostnameasusedinDNSentryoranIPaddressvalue:
address=<192.168.2.100>
changeDate()
Thisfunctionworkswithdatevaluesandmanipulatesthoseatruntimebyaddingorremovingadatevalueoffset.Youcanmanipulateseveraldatefieldssuchas:year,month,day,hour,minuteorsecond.
Letusclarifythiswithasimpleexampleforthisfunction:
<echo><message>citrus:changeDate('01.01.2000','+1y+1M+1d')</message></echo><echo><message>citrus:changeDate(citrus:currentDate(),'-1M')</message></echo>
Functionoutput:
02.02.200113.04.2013
Asyoucanseethechangedatefunctionworksonstaticdatevaluesordynamicvariablevaluesorfunctionslikecitrus:currentDate().Bydefaultthechangedatefunctionrequiresadateformatsuchasthecurrentdatefunction('dd.MM.yyyy').Youcanalsodefineacustomdateformat:
<echo><message>citrus:changeDate('2000-01-10','-1M-1d','yyyy-MM-dd')</message></echo>
Functionoutput:
1999-12-09
Withthisyouareabletomanipulatealldatevaluesofstaticordynamicnatureattestruntime.
readFile()
CitrusReferenceGuide
474Functions
![Page 475: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/475.jpg)
ThereadFilefunctionreadsafileresourcefromgivenfilepathandloadsthecompletefilecontentasfunctionresult.Thefilepathcanbeasystemfilepathaswellasaclasspathfileresource.Thefilepathcanhavetestvariablesaspartofthepathorfilename.Inadditiontothatthefilecontentcanalsohavetestvariablevaluesandotherfunctions.
Let'sseethisfunctioninaction:
<echo><message>citrus:readFile('classpath:some/path/to/file.txt')</message></echo><echo><message>citrus:readFile($filePath)</message></echo>
Thefunctionreadsthefilecontentandplacesthecontentatthepositionwherethefunctionhasbeencalled.ThismeansthatyoucanalsousethisfunctionaspartofStringsandmessagepayloadsforinstance.Thisisaverypowerfulwaytoextractlargemessagepartstoseparatefileresources.JustaddthereadFilefunctionsomewheretothemessagecontentandCitruswillloadtheextrafilecontentandplaceitrightintothemessagepayloadforyou.
message()
WhenmessagesareexchangedinCitrusthecontentisautomaticallysavedtoaninmemorystorageforfurtheraccessinthetestcase.Thatmeansthatfunctionsandtestactionscanaccessthemessagesthathavebeensentorreceivedwithinthetestcase.Themessagefunctionloadsamessagecontentfromthatmessagestore.Themessageisidentifiedbyitsname.Receiveandsendactionsusuallydefinethemessagename.Nowwecanloadthemessagepayloadwiththatname.
Let'sseethisfunctioninaction:
<echo><message>citrus:message(myRequest.payload())</message></echo>
ThefunctionaboveloadsthemessagenamedmyRequestfromthelocalmemorystore.Thisrequiresasendorreceiveactiontohavehandledthemessagebeforeinthesametestcase.
CitrusReferenceGuide
475Functions
![Page 476: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/476.jpg)
XMLDSL
<sendendpoint="someEndpoint"><messagename="myRequest"><payload>Somepayload</payload></message></send>
JavaDSL
send("someEndpoint").name("myRequest").payload("Somepayload");
Thenameofthemessageisimportant.Otherwisethemessagecannotbefoundinthelocalmessagestore.Note:amessagecaneitherbereceivedorsentwithanameinordertobestoredinthelocalmessagestore.Themessagefunctionisthenabletoaccessthemessagebyitsname.Inthefirstexamplethepayload()hasbeenloaded.Ofcoursewecanalsoaccessheaderinformation.
<echo><message>citrus:message(myRequest.header('Operation'))</message></echo>
ThesampleaboveloadstheheaderOperationofthemessage.
InJavaDSLthemessagestoreisalsoaccessibleovertheTestContext.
xpath()
ThexpathfunctionevaluatesaXpathexpressionsonsomeXMLsourceandreturnstheexpressionresultasString.
<echo><message><![CDATA[citrus:xpath('<message><id>1000</id></text>Sometextcontent</text></message>','/message/id')]]></echo>
TheXMLsourceisgivenasfirstfunctionparameterandcanbeloadedindifferentways.IntheexampleaboveastaticXMLsourcehasbeenused.WecouldloadtheXMLcontentfromexternalfileorjustuseatestvariable.
CitrusReferenceGuide
476Functions
![Page 477: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/477.jpg)
<echo><message><![CDATA[citrus:xpath(citrus:readFile('some/path/to/file.xml'),'/message/id')]]></echo>
Alsoaccessingthelocalmessagestoreisvalidhere:
<echo><message><![CDATA[citrus:xpath(citrus:message(myRequest.payload()),'/message/id')]]></message</echo>
Thiscombinationisquitepowerfulasallpreviouslyexchangedmessagesinthetestareautomaticallystoredtothelocalmessagestore.Reusingdynamicmessagevaluesfromothermessagesbecomesveryeasythen.
jsonPath()
ThejsonPathfunctionevaluatesaJsonPathexpressionsonsomeJSONsourceandreturnstheexpressionresultasString.
<echo><message><![CDATA[citrus:jsonPath('"message":"id":1000,"text":"Sometextcontent"','$.message.id')]]></echo>
TheJSONsourceisgivenasfirstfunctionparameterandcanbeloadedindifferentways.IntheexampleaboveastaticJSONsourcehasbeenused.WecouldloadtheJSONcontentfromexternalfileorjustuseatestvariable.
<echo><message><![CDATA[citrus:jsonPath($jsonSource,'$.message.id')]]></message></echo>
Alsoaccessingthelocalmessagestoreisvalidhere:
<echo><message><![CDATA[citrus:jsonPath(citrus:message(myRequest.payload()),'$.message.id')]]></echo>
CitrusReferenceGuide
477Functions
![Page 478: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/478.jpg)
Thiscombinationisquitepowerfulasallpreviouslyexchangedmessagesinthetestareautomaticallystoredtothelocalmessagestore.Reusingdynamicmessagevaluesfromothermessagesbecomesveryeasythen.
CitrusReferenceGuide
478Functions
![Page 479: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/479.jpg)
ValidationmatcherMessagevalidationinCitrusisessential.Theframeworkoffersseveralvalidationmechanismsfordifferentmessagetypesandformats.Withtestvariablesweareabletocheckforsimplevalueequality.Weensurethatmessageentriesareequaltopredefinedexpectedvalues.Validationmatcheraddpowerfulassertionfunctionalityontopofthat.YoujustcanusethepredefinedvalidationmatcherfunctionalitiesinordertoperformmorecomplexassertionslikecontainsorisNumberinyourvalidationstatements.
ThefollowingsectionsdescribetheCitrusdefaultvalidationmatcherimplementationsthatarereadyforusage.Thematcherimplementationsshouldcoverthebasicassertionsoncharactersequencesandnumbers.Ofcourseyoucanaddcustomvalidationmatcherimplementationsinordertomeetyourveryspecificvalidationassertions,too.
Firstofallletushavealookatavalidationmatcherstatementinactionsoweunderstandhowtousetheminatestcase.
<message><payload><RequestMessage><MessageBody><Customer><Id>@greaterThan(0)@</Id><Name>@equalsIgnoreCase('foo')@</Name></Customer></MessageBody></RequestMessage></payload></message>
Thelistingabovedescribesanormalmessagevalidationblockinsideareceivetestaction.WeusesomeinlinemessagepayloadtemplateasCDATA.AsyouknowCitruswillcomparetheactualmessagepayloadtothisexpectedtemplateinDOMtreecomparison.Inadditiontothatyoucansimplyincludevalidationmatcherstatements.ThemessageelementIdisautomaticallyvalidatedtobeanumbergreaterthanzeroandtheNamecharactersequenceissupposedtomatch'foo'ignoringcasespellingconsiderations.
CitrusReferenceGuide
479ValidationMatchers
![Page 480: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/480.jpg)
Pleasenotethespecialvalidationmatchersyntax.Thestatementsaresurroundedwith'@'markersandareidentifiedbysomeuniquename.Theoptionalparameterspassedtothematcherimplementationstatetheexpectedvaluestomatch.
TipYoucanusevalidationmatcherwithallvalidationmechanisms-notonlywithXMLvalidation.Plaintext,JSON,SQLresultsetvalidationarealsosupported.
Asetofvalidationmatcherimplementationsisusuallycombinedtoavalidationmatcherlibrary.Thelibraryhasaprefixthatwillidentifythevalidationmatcherinsidethetestcase.Thedefaulttestframeworkvalidationmatcherlibraryusesadefaultprefix(citrus).Youcanwriteyourownvalidationmatcherlibraryusingyourownprefixinordertoextendthetestframeworkfunctionalitywheneveryouwant.
ThelibraryisbuiltintheSpringconfigurationandcontainsasetofvalidationmatcherthatareofpublicuse.
<citrus:validationmatcher-libraryid="testMatcherLibrary"prefix="foo:"><citrus:matchername="isNumber">class="com.consol.citrus.validation.matcher.core.IsNumberValidationMatcher"/><citrus:matchername="contains">class="com.consol.citrus.validation.matcher.core.ContainsValidationMatcher"/><citrus:matchername="customMatcher">ref="customMatcherBean"/>...</citrus:validationmatcher-library>
AsyoucanseethelibrarydefinesonetomanyvalidationmatchermemberseitherreferencedasnormalSpringbeanorbyitsimplementingJavaclassname.Citrusconstructsthelibraryandyouareabletousethevalidationmatcherinyourtestcasewiththeleadinglibraryprefixjustlikethis:
@foo:isNumber()@@foo:contains()@@foo:customMatcher()@
TipYoucanaddcustomvalidationmatcherimplementationsandcustomvalidationmatcherlibraries.Justuseacustomprefixforyourlibrary.ThedefaultCitrusvalidationmatcherlibraryusesnoprefix.SeenowthefollowingsectionsdescribingthedefaultvalidationvalidationmatcherinCitrus.
ignore()
CitrusReferenceGuide
480ValidationMatchers
![Page 481: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/481.jpg)
Theignorevalidationmatcherisaspecialmatcherthatignoresthevalueandisalwayspositiveinitsoutcome.Youshouldusetheignorevalidationmatcherwhenonlyvalidatingthepureexistenceofanelement.Thevalueisignoredbuttheelementhastobepresentinthemessagepayload.
<message><payload><RequestMessage><MessageBody><Customer><Id>@ignore()@</Id><Name>@equalsIgnoreCase('foo')@</Name></Customer></MessageBody></RequestMessage></payload></message>
Note
Theignorevalidationmatcheristheonlyvalidationmatcherthatisabletoskipthefunctionparameterbody.Soyoucanuseboth@ignore()@and@ignore@.
matchesXml()
TheXMLvalidationmatcherimplementationisthepossiblymostexcitingone,aswecanvalidatenestedXMLwithfullvalidationpower(e.g.ignoringelements,variablesupport).ThematcherchecksanestedXMLfragmenttocompareagainstexpectedXML.ForinstancewereceivefollowingXMLmessagepayloadforvalidation:
<GetCustomerMessage><CustomerDetails><Id>5</Id><Name>Christoph</Name><Configuration><![CDATA[<config><premium>true</premium><last-login>2012-02-24T23:34:23</last-login><link>http://www.citrusframework.org/customer/5</link></config>]]></Configuration></CustomerDetails></GetCustomerMessage>
CitrusReferenceGuide
481ValidationMatchers
![Page 482: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/482.jpg)
AsyoucanseethemessagepayloadcontainssomeconfigurationasnestedXMLdatainaCDATAsection.WecouldvalidatethisCDATAsectionasstaticcharactersequencecomparison,true.Butthetimestampchangesitsvaluecontinuously.ThisbreaksthestaticvalidationforCDATAelementsinXML.FortunatelythenewXMLvalidationmatcherprovidesasolutionforus:
<message><payload><GetCustomerMessage><CustomerDetails><Id>5</Id><Name>Christoph</Name><Configuration>citrus:cdataSection('@matchesXml('<config><premium>$isPremium</premium><last-login>@ignore@</last-login><link>http://www.citrusframework.org/customer/5</link></config>')@')</Configuration></CustomerDetails></GetCustomerMessage></payload></message>
WiththevalidationmatcheryouareabletovalidatethenestedXMLwithfullvalidationpower.IgnoringelementsispossibleandwecanalsousevariablesinourcontrolXML.
NoteNestedCDATAelementswithinotherCDATAsectionsarenotallowedbyXMLstandard.ThisiswhywecreatethenestedCDATAsectionontheflywiththefunctioncdataSection().###equalsIgnoreCase()
Thismatcherimplementationchecksforequalitywithoutanycasespellingconsiderations.Thematcherexpectsasingleparameterastheexpectedcharactersequencetocheckfor.
<value>@equalsIgnoreCase('foo')@</value>
contains()
Thismatchersearchesforacharactersequenceinsidetheactualvalue.Ifthecharactersequenceisnotfoundsomewherethematcherstartscomplaining.
<value>@contains('foo')@</value>
CitrusReferenceGuide
482ValidationMatchers
![Page 483: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/483.jpg)
Thevalidationmatcheralsoexistinacaseinsensitivevariant.
<value>@containsIgnoreCase('foo')@</value>
startsWith()
Thematcherimplementationassertsthatthegivenvaluestartswithacharactersequenceotherwisethematcherwillarisesomeerror.
<value>@startsWith('foo')@</value>
endsWith()
Endswithmatchervalidatesavaluetoendwithagivencharactersequence.
<value>@endsWith('foo')@</value>
matches()
Youcancheckavaluetomeetaregularexpressionwiththisvalidationmatcher.Thisisforinstanceveryusefulforemailaddressvalidation.
<value>@matches('[a-z0-9]')@</value>
matchesDatePattern()
Datevaluesarealwaysdifficulttocheckforequality.Especiallywhenyouhavemillisecondtimestampstodealwith.Thereforethedatepatternvalidationmatchershouldhavesomeimprovementforyou.Yousimplyvalidatethedateformatpatterninsteadofcheckingfortotalequality.
<value>@matchesDatePattern('yyyy-MM-dd')@</value>
Theexamplelistingusesadateformatpatternthatisexpected.Theactualdatevalueisparsedaccordingtothispatternandmaycauseerrorsincasethevalueisnovaliddatematchingthedesiredformat.
CitrusReferenceGuide
483ValidationMatchers
![Page 484: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/484.jpg)
isNumber()
Checkingonvaluestobeofnumericnatureisessential.Theactualvaluemustbeanumericnumberotherwisethematcherraiseserrors.Thematcherimplementationdoesnotevaluateanyparameters.
<value>@isNumber()@</value>
lowerThan()
Thismatcherchecksanumbertobelowerthanagiventhresholdvalue.
<value>@lowerThan(5)@</value>
greaterThan()
Thematcherimplementationwillcheckonnumericvaluestobegreaterthanaminimumvalue.
<value>@greaterThan(5)@</value>
isWeekday()
Thematcherworksondatevaluesandchecksthatagivendateevaluatestotheexpecteddayoftheweek.Theuserdefinestheexpecteddaybyitsnameinuppercasecharacters.Thematcherfailsincasethegivendateisanotherweekdaythanexpected.
<someDate>@isWeekday('MONDAY')@</someDate>
Possiblevaluesfortheexpecteddayoftheweekare:MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAYorSUNDAY.
Thefieldvaluehastobeadatevalueotherwisethematcherwillfailtoparsethedate.Thematcherrequiresadateformatwhichisdd.MM.yyyybydefault.Youcanchangethisdateformatasfollows:
<someDate>@isWeekday(MONDAY('yyyy-MM-dd'))@</someDate>
CitrusReferenceGuide
484ValidationMatchers
![Page 485: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/485.jpg)
Nowthematcherusesthecustomdateformatinordertoparsethedatevalueforevaluation.Thevalidationmatcheralsoworkswithdatetimevalues.Inthiscaseyouhavetogiveavaliddatetimeformatrespectively(e.g.FRIDAY('yyyy-MM-dd'T'hh:mm:ss')).
variable()
Thisisaveryspecialvalidationmatcher.Insteadofperformingavalidationlogicyoucansavetheactualvaluepassedtothevalidationmatcherasnewtestvariable.Thiscomesveryhandyasyoucanusethematcherwhereveryouwant:JSONmessagepayloads,XMLmessagepayloads,headersandsoon.
<value>@variable('foo')@</value>
Thevalidationmatchercreatesanewvariablefoowiththeactualelementvalueasvariablevalue.Whenleavingoutthecontrolvaluethefieldnameitselfisusedasvariablename.
<date>@variable()@</date>
Thiscreatesanewvariabledatewiththeactualelementvalueasvariablevalue.
dateRange()
Thematcherworksondatevaluesandchecksthatagivendateiswithintheexpecteddaterange.Theuserdefinestheexpecteddaterangebyspecifyingafrom-date,ato-dateandoptionallyadateformat.Thematcherfailswhenthegivendateliesoutsidetheexpecteddaterange.
<someDate>@dateRange('01-12-2015','31-12-2015','dd-MM-yyyy')@</someDate>
Possiblevalidvalueswouldbe'somedate'>='01-12-2015'and'somedate'<='31-12-2015'
Thedate-formatisoptionalandwhenomitteditisassumedthatalldatesmatchthedefaultdateformatyyyy-MM-dd.Whenspecifyingacustomdateformatusejava'sdateformatasareferenceforvaliddateformats.Onlydateswereusedintheexampleabovebutwecouldjustaseasilyuseddateandtimeasshownintheexamplebelow
CitrusReferenceGuide
485ValidationMatchers
![Page 486: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/486.jpg)
<someDate>@dateRange('2015.12.0107:00:00','2015.12.0119:00:00','yyyy.MM.ddHH:mm:ss')@</someDate
assertThat()
Hamcrestisaverypowerfulmatcherlibrarywithextraordinarymatcherimplementations.YoucanuseHamcrestmatchersalsoasCitrusvalidationmatcher.
<someValue>@assertThat(equalTo(foo))@</someValue>
InthelistingaboveweareusingtheequalTo()matcher.AllHamcrestmatchersaresurroundedbyaassertThatexpression.YouareabletocombineseveralHamcrestmatcherstheninordertoconstructverypowerfulvalidationlogic.Seethefollowingexamplesonwhatispossiblethen:
<someValue>@assertThat(equalTo(value))@</someValue><someValue>@assertThat(not(equalTo(other))@</someValue><someValue>@assertThat(is(not(other)))@</someValue><someValue>@assertThat(not(is(other)))@</someValue><someValue>@assertThat(equalToIgnoringCase(VALUE))@</someValue><someValue>@assertThat(containsString(lue))@</someValue><someValue>@assertThat(not(containsString(other)))@</someValue><someValue>@assertThat(startsWith(val))@</someValue><someValue>@assertThat(endsWith(lue))@</someValue><someValue>@assertThat(anyOf(startsWith(val),endsWith(lue)))@</someValue><someValue>@assertThat(allOf(startsWith(val),endsWith(lue)))@</someValue><someValue>@assertThat(isEmptyString())@</someValue><someValue>@assertThat(not(isEmptyString()))@</someValue><someValue>@assertThat(isEmptyOrNullString())@</someValue><someValue>@assertThat(nullValue())@</someValue><someValue>@assertThat(notNullValue())@</someValue><someValue>@assertThat(empty())@</someValue><someValue>@assertThat(not(empty())@</someValue><someValue>@assertThat(greaterThan(4))@</someValue><someValue>@assertThat(allOf(greaterThan(4),lessThan(6),not(lessThan(5)))@</someValue><someValue>@assertThat(is(not(greaterThan(5))))@</someValue><someValue>@assertThat(greaterThanOrEqualTo(5))@</someValue><someValue>@assertThat(lessThan(5))@</someValue><someValue>@assertThat(not(lessThan(1)))@</someValue><someValue>@assertThat(lessThanOrEqualTo(4))@</someValue><someValue>@assertThat(hasSize(5))@</someValue>
Citruswillautomaticallyperformvalidationmatchersontheelementvalue.Onlyifallmatchersaresatisfiedthevalidationwillpass.
CitrusReferenceGuide
486ValidationMatchers
![Page 487: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/487.jpg)
CitrusReferenceGuide
487ValidationMatchers
![Page 488: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/488.jpg)
DatadictionariesDatadictionariesinCitrusprovideanewwaytomanipulatemessagepayloaddatabeforeamessageissentorreceived.Thedictionarydefinesasetofkeysandrespectivevalues.Justlikeeveryotherdictionaryitisusedtotranslatethings.Inourcasewetranslatemessagedataelements.
Youcantranslatecommonmessageelementsthatareusedwidelythroughoutyourdomainmodel.AsCitrusdealswithdifferenttypesofmessagedata(e.g.XML,JSON)wehavedifferentdictionaryimplementationsthataredescribedinthenextsections.
XMLdatadictionaries
XMLdatadictionariesdoapplytoXMLmessageformatpayloads,ofcourse.IngeneralweaddadictionarytothebasicCitrusSpringapplicationcontextinordertomakethedictionaryvisibletoalltestcases:
<citrus:xml-data-dictionaryid="nodeMappingDataDictionary"><citrus:mappings><citrus:mappingpath="TestMessage.MessageId"value="$messageId"/><citrus:mappingpath="TestMessage.CorrelationId"value="$correlationId"/><citrus:mappingpath="TestMessage.User"value="Christoph"/><citrus:mappingpath="TestMessage.TimeStamp"value="citrus:currentDate()"/></citrus:mappings></citrus:xml-data-dictionary>
AsyoucanseethedictionaryisnothingbutanormalSpringbeandefinition.TheNodeMappingDataDictionaryimplementationreceivesamapofkeyvaluepairswherethekeyisamessageelementpathexpression.ForXMLpayloadsthemessageelementtreeistraversedsothepathexpressionisbuiltforanexactmessageelementinsidethepayload.Ifmatchedtherespectivevalueissetaccordinglythroughthedictionary.
Besidesdefiningthedictionarykeyvaluemappingsaspropertymapinsidethebeandefinitionwecanextractthemappingdatatoanexternalfile.
<citrus:xml-data-dictionaryid="nodeMappingDataDictionary"><citrus:mapping-filepath="classpath:com/consol/citrus/sample.dictionary"/></citrus:xml-data-dictionary>
ThemappingfilecontentjustlookslikeanormalpropertyfileinJava:
CitrusReferenceGuide
488Datadictionary
![Page 489: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/489.jpg)
TestMessage.MessageId=$messageIdTestMessage.CorrelationId=$correlationIdTestMessage.User=ChristophTestMessage.TimeStamp=citrus:currentDate()
YoucansetanymessageelementvalueinsidetheXMLmessagepayload.ThepathexpressionalsosupportsXMLattributes.Justusetheattributenameaslastpartofthepathexpression.LetushaveacloserlookatasampleXMLmessagepayloadwithattributes:
<TestMessage><Username="Christoph"age="18"/></TestMessage>
WiththissampleXMLpayloadgivenwecanaccesstheattributesinthedatadictionaryasfollows:
<citrus:mappingpath="TestMessage.User.name"value="$userName"/><citrus:mappingpath="TestMessage.User.age"value="$userAge"/>
TheNodeMappingDataDictionaryimplementationiseasytouseandfitsthebasicneedsforXMLdatadictionaries.Themessageelementpathexpressionsareverysimpleanddofitbasicneeds.HoweverwhenmorecomplexXMLpayloadsapplyfortranslationwemightreachtheboundarieshere.
FormorecomplexXMLmessagepayloadsXPathdatadictionariesareveryeffective:
<citrus:xpath-data-dictionaryid="xpathMappingDataDictionary"><citrus:mappings><citrus:mappingpath="//TestMessage/MessageId"value="$messageId"/><citrus:mappingpath="//TestMessage/CorrelationId"value="$correlationId"/><citrus:mappingpath="//TestMessage/User"value="Christoph"/><citrus:mappingpath="//TestMessage/User/@id"value="123"/><citrus:mappingpath="//TestMessage/TimeStamp"value="citrus:currentDate()"/></citrus:mappings></citrus:xpath-data-dictionary>
AsexpectedXPathmappingexpressionsarewaymorepowerfulandcanalsohandleverycomplexscenarioswithXMLnamespaces,attributesandnodelists.JustlikethenodemappingdictionarytheXPathmappingdictionarydoesalsosupportvariables,functionsandanexternalmappingfile.
CitrusReferenceGuide
489Datadictionary
![Page 490: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/490.jpg)
XPathworksfinewithnamespaces.IngeneralitisgoodpracticetodefineanamespacecontextwhereyoumapnamespaceURIvalueswithprefixvalues.SoyourXPathexpressionisalwaysexactandevaluationisstrict.InCitrustheNamespaceContextBuilderwhichisalsoaddedasnormalSpringbeantotheapplicationcontextmanagesnamespacesusedinyourXPathexpressions.SeeourXMLandXPAthchaptersinthisdocumentationfordetaileddescriptionhowtoaccomplishfailsafeXPathexpressionswithnamespaces.
ThiscompletestheXMLdatadictionaryusageinCitrus.Lateronwewillseesomemoreadvanceddatadictionaryscenarioswherewewilldiscusstheusageofdictionaryscopesandmappingstrategies.ButbeforethatletushavealookatothermessageformatslikeJSONmessages.
JSONdatadictionaries
JSONdatadictionariescomplementwithXMLdatadictionaries.AsusualwehavetoaddtheJSONdatadictionarytothebasicSpringapplicationcontextfirst.OncethisisdonethedatadictionaryautomaticallyappliesforallJSONmessagepayloadsinCitrus.ThismeansthatallJSONmessagessentandreceivedgettranslatedwiththeJSONdatadictionaryimplementation.
Citrususesmessagetypesinordertoevaluatewhichdatadictionarymayfittothemessagethatiscurrentlyprocessed.Asusualyoucandefinethemessagetypedirectlyinyourtestcaseasattributeinsidethesendingandreceivingmessageaction.
LetusseeasimpledictionaryforJSONdata:
<citrus:json-data-dictionaryid="jsonMappingDataDictionary"><citrus:mappings><citrus:mappingpath="TestMessage.MessageId"value="$messageId"/><citrus:mappingpath="TestMessage.CorrelationId"value="$correlationId"/><citrus:mappingpath="TestMessage.User"value="Christoph"/><citrus:mappingpath="TestMessage.TimeStamp"value="citrus:currentDate()"/></citrus:mappings></citrus:json-data-dictionary>
ThemessagepathexpressionsdolookverysimilartothoseusedinXMLdatadictionaries.HerethepathexpressionkeysdoapplytotheJSONobjectgraph.SeethefollowingsampleJSONdatawhichperfectlyappliestothedictionaryexpressionsabove.
"TestMessage":"MessageId":"1122334455",
CitrusReferenceGuide
490Datadictionary
![Page 491: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/491.jpg)
"CorrelationId":"100000001","User":"Christoph","TimeStamp":1234567890
ThepathexpressionswillmatchaveryspecificmessageelementinsidetheJSONobjectgraph.Thedictionarywillautomaticallysetthemessageelementvaluesthen.ThepathexpressionsareeasytouseasyoucantraversetheJSONobjectgraphveryeasy.
Ofcoursethedatadictionarydoesalsosupporttestvariables,functions.AlsoveryinterestingistheusageofJSONarrays.AJSONarrayelementisreferencedinadatadictionarylikethis:
<citrus:mappingpath="TestMessage.Users[0]"value="Christoph"/><citrus:mappingpath="TestMessage.Users[1]"value="Julia"/>
TheUserselementisaJSONarray,sowecanaccesstheelementswithindex.NestingJSONobjectsandarraysisalsosupportedsoyoucanalsohandlemorecomplexJSONdata.
TheJsonMappingDataDictionaryimplementationiseasytouseandfitsthebasicneedsforJSONdatadictionaries.Themessageelementpathexpressionsareverysimpleanddofitbasicneeds.HoweverwhenmorecomplexJSONpayloadsapplyfortranslationwemightreachtheboundarieshere.
FormorecomplexJSONmessagepayloadsJsonPathdatadictionariesareveryeffective:
<citrus:json-path-data-dictionaryid="jsonMappingDataDictionary"><citrus:mappings><citrus:mappingpath="$.TestMessage.MessageId"value="$messageId"/><citrus:mappingpath="$..CorrelationId"value="$correlationId"/><citrus:mappingpath="$..Users[0]"value="Christoph"/><citrus:mappingpath="$.TestMessage.TimeStamp"value="citrus:currentDate()"/></citrus:mappings></citrus:json-path-data-dictionary>
JsonPathmappingexpressionsarewaymorepowerfulandcanalsohandleverycomplexscenarios.YoucanapplyforallelementsnamedCorrelationIdinonesingleentryforinstance.
Dictionaryscopes
CitrusReferenceGuide
491Datadictionary
![Page 492: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/492.jpg)
NowthatwehavelearnedhowtoadddatadictionariestoCitrusweneedtodiscusssomeadvancedtopics.Datadictionaryscopesdodefinetheboundarieswherethedictionarymayapply.Bydefaultdatadictionariesareglobalscopedictionaries.ThismeansthatthedatadictionaryappliestoallmessagessentandreceivedwithCitrus.OfcoursemessagetypesareconsideredsoXMLdatadictionariesdoonlyapplytoXMLmessagetypes.Howeverglobalscopedictionarieswillbeactivatedthroughoutalltestcasesandactions.
Youcanoverwritethedictionaryscope.Forinstanceinordertouseanexplicitscope.Whenthisisdonethedictionarywilnotapplyautomaticallybuttheuserhastoexplicitlysetthedatadictionaryinsendingorreceivingtestaction.Thiswayyoucanactivatethedictionarytoaveryspecialsetoftestactions.
<citrus:xml-data-dictionaryid="specialDataDictionary"global-scope="false"><citrus:mapping-filepath="classpath:com/consol/citrus/sample.dictionary"/></citrus:xml-data-dictionary>
Wesettheglobalscopepropertytofalsesothedictionaryishandledinexplicitscope.Thismeansthatyouhavetosetthedatadictionaryexplicitlyinyourtestactions:
XMLDSL
<sendendpoint="myEndpoint"><messagedata-dictionary="specialDataDictionary"><payload><TestMessage>HelloCitrus"/TestMessage></payload></message></send>
JavaDSLdesignerandrunner
@CitrusTestpublicvoiddictionaryTest()send(myEndpoint).payload("<TestMessage>HelloCitrus"/TestMessage>").dictionary("specialDataDictionary");
Thesampleaboveisasendingtestactionwithanexplicitdatadictionaryreferenceset.Beforesendingthemessagethedictionaryisaskedfortranslation.Soallmatchingmessageelementvalueswillbesetbythedictionaryaccordingly.Otherglobaldata
CitrusReferenceGuide
492Datadictionary
![Page 493: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/493.jpg)
dictionariesdoalsoapplyforthismessagebuttheexplicitdictionarywillalwaysoverwritethemessageelementvalues.
Pathmappingstrategies
Anotheradvancedtopicaboutdatadictionariesisthepathmappingstrategy.WhenusingsimplepathexpressionsthedefaultstrategyisalwaysEXACT.Thismeansthatthepathexpressionhastoevaluateexactlytoamessageelementwithinthepayloaddata.Andonlythisexactmessageelementistranslated.
Youcansetyourownpathmappingstrategyinordertochangethisbehavior.ForinstanceanothermappingstrategywouldbeSTARS_WITH.Allelementsaretranslatedthatstartwithacertainpathexpression.Letusclarifythiswithanexample:
<citrus:xml-data-dictionaryid="nodeMappingDataDictionary"mapping-strategy="STARTS_WITH"><citrus:mappings><citrus:mappingpath="TestMessage.Property"value="citrus:randomString()"/></citrus:mappings></citrus:xml-data-dictionary>
NowwiththepathmappingstrategysettoSTARS_WITHallmessageelementpathexpressionsstartingwithTestMessage.Propertywillfindtranslationinthisdictionary.Followingsamplemessagepayloadwouldbetranslatedaccordingly:
<TestMessage><Property>XXX</Property><PropertyName>XXX</PropertyName><PropertyValue>XXX</PropertyValue></TestMessage>
AllchildelementsofTestMessagestartingwithPropertywillbetranslatedwiththisdatadictionary.IntheresultingmessagepayloadCitruswillusearandomstringasvaluefortheseelementsasweusedthecitrus:randomString()functioninthedictionarymapping.
ThenextmappingstrategywouldbeENDS_WITH.Nosurpriseshere-thismappingstrategylooksformessageelementsthatendwithacertainpathexpression.Againasimpleexamplewillclarifythisforyou.
<citrus:xml-data-dictionaryid="nodeMappingDataDictionary"mapping-strategy="ENDS_WITH"><citrus:mappings><citrus:mappingpath="Id"value="citrus:randomNumber()"/>
CitrusReferenceGuide
493Datadictionary
![Page 494: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/494.jpg)
</citrus:mappings></citrus:xml-data-dictionary>
Againletusseesomesamplemessagepayloadforthisdictionaryusage:
<TestMessage><RequestId>XXX</RequestId><Properties><Property><PropertyId>XXX</PropertyId><PropertyValue>XXX</PropertyValue></Property><Property><PropertyId>XXX</PropertyId><PropertyValue>XXX</PropertyValue></Property></Properties></TestMessage>
InthissampleallmessageelementsendingwithIdwouldbetranslatedwitharandomnumber.Nomatterwhereinthemessagetreetheelementsarelocated.Thisisquiteusefulbutalsoverypowerful.Sobecarefultousethisstrategyinglobaldatadictionariesasitmaytranslatemessageelementsthatyouwouldnotexpectinthefirstplace.
CitrusReferenceGuide
494Datadictionary
![Page 495: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/495.jpg)
TestactorsTheconceptoftestactorscametoourmindwhenreusingCitrustestcasesinend-to-endtestscenarios.UsuallyCitrussimulatesallinterfacepartnerswithinatestcasewhichisgreatforcontinuousintegrationtesting.Inend-to-endintegrationtestscenariossomeofourinterfacepartnersmayberealandalive.SomeotherinterfacepartnersstillrequireCitrussimulationlogic.
ItwouldbegreatifwecouldreusetheCitrusintegrationtestsinthistestsetupaswehavethecompletetestflowofmessagesavailableintheCitrustests.Weonlyhavetoremovethesimulatedsend/receiveactionsforthoserealinterfacepartnerapplicationswhichareavailableinourend-to-endtestsetup.
Withtestactorswehavetheopportunitytolinktestactions,inparticularsend/receivemessageactions,toatestactor.Thetestactorcanbedisabledinconfigurationveryeasyandfollowingfromthatalllinkedsend/receiveactionsaredisabled,too.OneCitrustestcaseisrunnablewithdifferenttestsetupscenarioswheredifferentpartnerapplicationsontheonehandareavailableasreallifeapplicationsandontheotherhandmyrequiresimulation.
Definetestactors
FirstthingtodoistodefineoneormoretestactorsinCitrusconfiguration.Atestactorrepresentsaparticipatingparty(e.g.interfacepartner,backendapplication).WewritethetestactorsintothecentralSpringapplicationcontext.WecanuseaspecialCitrusSpringXMLschemasodefinitionsarequiteeasy:
<citrus:actorid="travelagency"name="TRAVEL_AGENCY"/><citrus:actorid="royalairline"name="ROYAL_AIRLINE"/><citrus:actorid="smartariline"name="SMART_AIRLINE"/>
Thelistingabovedefinesthreetestactorsparticipatinginourtestscenario.AtravelagencyapplicationwhichissimulatedbyCitrusasacallingclient,thesmartairlineapplicationandaroyalairlineapplication.Nowwehavethetestactorsdefinedwecanlinkthosetomessagesender/receiverinstancesand/ortestactionswithinourtestcase.
Linktestactors
CitrusReferenceGuide
495Testactors
![Page 496: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/496.jpg)
Weneedtolinkthetestactorstomessagesendandreceiveactionsinourtestcases.Wecandothisintwodifferentways.Firstwecansetatestactorreferenceonamessagesenderandmessagereceiver.
<citrus-jms:sync-endpointid="royalAirlineBookingEndpoint"destination-name="$royal.airline.request.queue"actor="royalairline"/>
Nowalltestactionsthatareusingthesemessagereceiverandmessagesenderinstancesarelinkedtothetestactor.Inadditiontothatyoucanalsoexplicitlylinktestactionstotestactorsinatest.
<receiveendpoint="royalAirlineBookingEndpoint"actor="royalairline"><message>[...]</message></receive>
<sendendpoint="royalAirlineBookingEndpoint"actor="royalairline"><message>[...]</message></send>
Thisexplicitlylinkstestactorstotestactionssoyoucandecidewhichlinkshouldbesetwithouthavingtorelyonthemessagereceiverandsenderconfiguration.
Disabletestactors
Usuallybothairlineapplicationsaresimulatedinourintegrationtests.Butthistimewewanttochangethisbyintroducingaroyalairlineapplicationwhichisonlineasarealapplicationinstance.SoweneedtoskipallsimulatedmessageinteractionsfortheroyalairlineapplicationinourCitrustests.Thisiseasyaswehavelinkedallsend/receiveactionstooneofourtestactors.Sowencandisabletheroyalairlinetestactorinourconfiguration:
<citrus:actorid="royalairline"name="ROYAL_AIRLINE"disabled="true"/>
Anytestactionlinkedtothistestactorisnowskipped.Asweintroducedarealroyalairlineapplicationinourtestscenariotherequestsgetansweredandthetestshouldbesuccessfulwithinthisend-to-endtestscenario.Thetravelagencyandthesmartairline
CitrusReferenceGuide
496Testactors
![Page 497: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/497.jpg)
stillgetsimulatedbyCitrus.ThisisaperfectwayofreusingintegrationtestsindifferenttestscenarioswhereyouenableanddisablesimulatedparticipatingpartiesinCitrus.
ImportantServerportsmaybeofspecialinterestwhendealingwithdifferenttestscenarios.YoumayhavetoalsodisableaCitrusembeddedJettyserverinstanceinordertoavoidportbindingconflictsandyoumayhavetowireendpointURIsaccordinglybeforeexecutingatest.ThereallifeapplicationmaynotusethesameportandipastheCitrusembeddedserversforsimulation.
CitrusReferenceGuide
497Testactors
![Page 498: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/498.jpg)
TestsuiteactionsAtestframeworkshouldalsoprovidethefunctionalitytodosomeworkbeforeandafterthetestrun.Youcouldthinkofpreparing/deletingthedatainadatabaseorstarting/stoppingaserverinthissectionbefore/afteratestrun.ThesetasksfitbestintotheinitializationandcleanupphasesofCitrus.
NoteItisimportanttonoticethattheCitrusconfigurationcomponentsthatwearegoingtouseinthenextsectionbelongtoaseparateXMLnamespacecitrus-test.WehavetoaddthenamespacedeclarationtotheXMLrootelementofourXMLconfigurationfileaccordingly.
<spring:beansxmlns="http://www.citrusframework.org/schema/testcase"xmlns:spring="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:citrus-test="http://www.citrusframework.org/schema/testcase"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.citrusframework.org/schema/testcasehttp://www.citrusframework.org/schema/testcase/citrus-testcase.xsd">
[...]
</beans>
Beforesuite
Youcaninfluencethebehaviorofatestrunintheinitializationphaseactuallybeforethetestsareexecuted.Seethenextcodeexampletofindouthowitworkswithactionsthattakeplacebeforethefirsttestisexecuted:
XMLConfig
<citrus:before-suiteid="actionsBeforeSuite"><citrus:actions><!--listofactionsbeforesuite--></citrus:actions></citrus:before-suite>
CitrusReferenceGuide
498Testsuite
![Page 499: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/499.jpg)
TheCitrusconfigurationcomponentholdsalistofCitrustestactionsthatgetexecutedbeforethetestsuiterun.YoucanaddallCitrustestactionshereasyouwoulddoinanormaltestcasedefinition.
XMLConfig
<citrus:before-suiteid="actionsBeforeSuite"><citrus:actions><citrus-test:sqldataSource="testDataSource"/><citrus-test:statement>CREATETABLEPERSON(IDinteger,NAMEchar(250))</citrus-test:statement</citrus-test:sql></citrus:actions></citrus:before-suite>
NotethatwemustusetheCitrustestcasenamespaceforthenestedtestactiondefinitions.WeaccessthedatabaseandcreateatablePERSONwhichisobviouslyneededinourtestcases.Youcanthinkofseveralactionsheretopreparethedatabaseforinstance.
TipCitrusoffersspecialstartupandshutdownactionsthatmaystartandstopserverimplementationsautomatically.ThismightbehelpfulwhendealingwithHttpserversorWebServicecontainerslikeJetty.Youcanalsothinkofstarting/stoppingaJMSbrokerbeforeatestrun.
SofarwehaveusedXMLDSLactionsinbeforesuiteconfiguration.NowifyouexclusivelywanttouseJavaDSLyoucandothesamewithaddingacustomclassthatextendsTestDesignerBeforeSuiteSupportorTestRunnerBeforeSuiteSupport.
JavaDSLdesigner
publicclassMyBeforeSuiteextendsTestDesignerBeforeSuiteSupport@OverridepublicvoidbeforeSuite(TestDesignerdesigner)designer.echo("Thisactionshouldbeexecutedbeforesuite");
ThecustomimplementationextendsTestDesignerBeforeSuiteSupportandthereforehastoimplementthemethodbeforeSuite.ThismethodaddsomeJavaDSLdesignerlogictothebeforesuite.Thedesignerinstanceisinjectedasmethodargument.Youcan
CitrusReferenceGuide
499Testsuite
![Page 500: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/500.jpg)
useallJavaDSLmethodstothisdesignerinstance.Citruswillautomaticallyfindandexecutethebeforesuitelogic.WeonlyneedtoaddthisclasstotheSpringbeanapplicationcontext.Youcandothisexplicitly:
<beanid="myBeforeSuite"class="my.company.citrus.MyBeforeSuite"/>
OfcourseyoucanalsouseotherSpringbeanmechanismssuchascomponent-scansheretoo.TherespectivetestrunnerimplementationextendstheTestRunnerBeforeSuiteSupportandgetsatestrunnerinstanceasmethodargumentinjected.
JavaDSLrunner
publicclassMyBeforeSuiteextendsTestRunnerBeforeSuiteSupport@OverridepublicvoidbeforeSuite(TestRunnerrunner)runner.echo("Thisactionshouldbeexecutedbeforesuite");
Youcanhavemanybefore-suiteconfigurationcomponentswithdifferentidsinaCitrusproject.Bydefaultthecontainersarealwaysexecuted.Butyoucanrestricttheaftersuiteactioncontainerexecutionbydefiningasuitename,testgroupnames,environmentorsystempropertiesthatshouldmatchaccordingly:
XMLConfig
<citrus:before-suiteid="actionsBeforeSuite"suites="databaseSuite"groups="e2e"><citrus:actions><citrus-test:sqldataSource="testDataSource"/><citrus-test:statement>CREATETABLEPERSON(IDinteger,NAMEchar(250))</citrus-test:statement</citrus-test:sql></citrus:actions></citrus:before-suite>
TheabovebeforesuitecontainerisonlyexecutedwiththetestsuitecalleddatabaseSuiteorwhenthetestgroupe2eisdefined.TestgroupsandsuitenamesareonlysupportedwhenusingtheTestNGunittestframework.UnfortunatelyJUnitdoesnotallowtohookintosuiteexecutionaseasilyasTestNGdoes.Thisiswhyaftersuite
CitrusReferenceGuide
500Testsuite
![Page 501: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/501.jpg)
actioncontainersarenotrestrictedinexecutionwhenusingCitruswiththeJUnittestframework.Youcandefinemultiplesuitenamesandtestgroupswithcommadelimitedstringsasattributevalues.
WhenusingtheJavaDSLbeforesuitesupportyoucansetsuitenamesandtestgroupfiltersbysimplycallingtherespectivesettermethodsinyourcustomimplementation.
<beanid="myBeforeSuite"class="my.company.citrus.MyBeforeSuite"><propertyname="suiteNames"><list><value>databaseSuite</value></list></property><propertyname="testGroups"><list><value>e2e</value></list></property></bean>
Environmentorsystempropertiesaredefinedaslistofkey-valuepairs.Whenspecifiedthepropertieshavetobepresentwithrespectivevalue.Incasethepropertyvalueisleftoutinconfigurationthepropertymustsimplyexistsonthesysteminordertoenablethebeforesuitesequenceinthattestrun.
XMLConfig
<citrus:before-suiteid="actionsBeforeSuite"suites="databaseSuite"groups="e2e"><citrus:env><citrus:propertyname="USER"/></citrus:env><citrus:system><citrus:propertyname="test-stage"value="e2e"/></citrus:system><citrus:actions><citrus-test:sqldataSource="testDataSource"/><citrus-test:statement>CREATETABLEPERSON(IDinteger,NAMEchar(250))</citrus-test:statement</citrus-test:sql></citrus:actions></citrus:before-suite>
IntheexampleabovethesuitesequencewillonlyapplyonenvironmentswithUSERpropertysetandthesystempropertytest-stagemustbesettoe2e.Otherwisethesequenceexecutionisskipped.
CitrusReferenceGuide
501Testsuite
![Page 502: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/502.jpg)
Aftersuite
Atestrunmayrequirethetestenvironmenttobeclean.ThereforeitisagoodideatopurgeallJMSdestinationsorcleanupthedatabaseafterthetestruninordertoavoiderrorsinfollow-uptestruns.Justlikewepreparedsomedatainactionsbeforesuitewecancleanupthetestruninactionsafterthetestsarefinished.TheSpringbeansyntaxhereisnotsignificantlydifferenttothoseinbeforesuitesection:
XMLConfig
<citrus:after-suiteid="actionsAfterSuite"><citrus:actions><!--listofactionsaftersuite--></citrus:actions></citrus:after-suite>
Againwegivetheaftersuiteconfigurationcomponentauniqueidwithintheconfigurationandputonetomanytestactionsasnestedconfigurationelementstothelistofactionsexecutedafterthetestsuiterun.
XMLConfig
<citrus:after-suiteid="actionsAfterSuite"><citrus:actions><citrus-test:sqldataSource="testDataSource"/><citrus-test:statement>DELETEFROMTABLEPERSON</citrus-test:statement></citrus-test:sql></citrus:actions></citrus:after-suite>
WehavetousetheCitrustestcaseXMLnamespacewhendefiningnestedtestactionsinaftersuitelist.Wejustremovealldatafromthedatabasesowedonotinfluencefollow-uptests.Quitesimpleisn'tit!?
OfcoursewecanalsodefineJavaDSLaftersuiteactions.YoucandothisbyaddingacustomclassthatextendsTestDesignerAfterSuiteSupportorTestRunnerAfterSuiteSupport.
JavaDSLdesigner
publicclassMyAfterSuiteextendsTestDesignerAfterSuiteSupport@OverridepublicvoidafterSuite(TestDesignerdesigner)designer.echo("Thisactionshouldbeexecutedaftersuite");
CitrusReferenceGuide
502Testsuite
![Page 503: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/503.jpg)
ThecustomimplementationextendsTestDesignerAfterSuiteSupportandthereforehastoimplementthemethodafterSuite.ThismethodaddsomeJavaDSLdesignerlogictotheaftersuite.Thedesignerinstanceisinjectedasmethodargument.YoucanuseallJavaDSLmethodstothisdesignerinstance.Citruswillautomaticallyfindandexecutetheaftersuitelogic.WeonlyneedtoaddthisclasstotheSpringbeanapplicationcontext.Youcandothisexplicitly:
<beanid="myAfterSuite"class="my.company.citrus.MyAfterSuite"/>
OfcourseyoucanalsouseotherSpringbeanmechanismssuchascomponent-scansheretoo.TherespectivetestrunnerimplementationextendstheTestRunnerAfterSuiteSupportandgetsatestrunnerinstanceasmethodargumentinjected.
JavaDSLrunner
publicclassMyAfterSuiteextendsTestRunnerAfterSuiteSupport@OverridepublicvoidafterSuite(TestRunnerrunner)runner.echo("Thisactionshouldbeexecutedaftersuite");
Youcanhavemanyafter-suiteconfigurationcomponentswithdifferentidsinaCitrusproject.Bydefaultthecontainersarealwaysexecuted.Butyoucanrestricttheaftersuiteactioncontainerexecutionbydefiningasuitename,testgroupnames,environmentorsystempropertiesthatshouldmatchaccordingly:
XMLConfig
<citrus:after-suiteid="actionsAfterSuite"suites="databaseSuite"groups="e2e"><citrus:actions><citrus-test:sqldataSource="testDataSource"/><citrus-test:statement>DELETEFROMTABLEPERSON</citrus-test:statement></citrus-test:sql></citrus:actions></citrus:after-suite>
CitrusReferenceGuide
503Testsuite
![Page 504: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/504.jpg)
TheaboveaftersuitecontainerisonlyexecutedwiththetestsuitecalleddatabaseSuiteorwhenthetestgroupe2eisdefined.TestgroupsandsuitenamesareonlysupportedwhenusingtheTestNGunittestframework.UnfortunatelyJUnitdoesnotallowtohookintosuiteexecutionaseasilyasTestNGdoes.ThisiswhyaftersuiteactioncontainersarenotrestrictedinexecutionwhenusingCitruswiththeJUnittestframework.
Youcandefinemultiplesuitenamesandtestgroupswithcommadelimitedstringsasattributevalues.
WhenusingtheJavaDSLbeforesuitesupportyoucansetsuitenamesandtestgroupfiltersbysimplycallingtherespectivesettermethodsinyourcustomimplementation.
<beanid="myAfterSuite"class="my.company.citrus.MyAfterSuite"><propertyname="suiteNames"><list><value>databaseSuite</value></list></property><propertyname="testGroups"><list><value>e2e</value></list></property></bean>
Environmentorsystempropertiesaredefinedaslistofkey-valuepairs.Whenspecifiedthepropertieshavetobepresentwithrespectivevalue.Incasethepropertyvalueisleftoutinconfigurationthepropertymustsimplyexistsonthesysteminordertoenablethebeforesuitesequenceinthattestrun.
XMLConfig
<citrus:after-suiteid="actionsBeforeSuite"suites="databaseSuite"groups="e2e"><citrus:env><citrus:propertyname="USER"/></citrus:env><citrus:system><citrus:propertyname="test-stage"value="e2e"/></citrus:system><citrus:actions><citrus-test:sqldataSource="testDataSource"/><citrus-test:statement>DELETEFROMTABLEPERSON</citrus-test:statement></citrus-test:sql></citrus:actions></citrus:after-suite>
CitrusReferenceGuide
504Testsuite
![Page 505: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/505.jpg)
IntheexampleabovethesuitesequencewillonlyapplyonenvironmentswithUSERpropertysetandthesystempropertytest-stagemustbesettoe2e.Otherwisethesequenceexecutionisskipped.
Beforetest
BeforeeachtestisexecuteditalsomightsoundreasonabletopurgeallJMSqueuesforinstance.IncaseaprevioustestfailssomemessagesmightbeleftintheJMSqueues.Alsothedatabasemightbeindirtystate.Thefollow-uptestthenwillbeconfrontedwiththeseinvalidmessagesanddata.PurgingallJMSdestinationsbeforeatestisthereforeagoodidea.Justlikewepreparedsomedatainactionsbeforesuitewecancleanupthedatabeforeateststartstoexecute.
XMLConfig
<citrus:before-testid="defaultBeforeTest"><citrus:actions><!--listofactionsbeforetest--></citrus:actions></citrus:before-test>
Thebeforetestconfigurationcomponentreceivesauniqueidandalistoftestactionsthatgetexecutedbeforeatestcaseisstarted.Thecomponentreceivesusualtestactiondefinitionsjustlikeyouwouldwritetheminanormaltestcasedefinition.Seetheexamplebelowhowtoaddtestactions.
XMLConfig
<citrus:before-testid="defaultBeforeTest"><citrus:actions><citrus-test:echo><citrus-test:message>Thisisexecutedbeforeeachtest!</citrus-test:message></citrus-test:echo></citrus:actions></citrus:before-test>
NotethatwemustusetheCitrustestcaseXMLnamespaceforthenestedtestactiondefinitions.YouhavetodeclaretheXMLnamespacesaccordinglyinyourconfigurationrootelement.Theechotestactionisnowexecutedbeforeeachtestinourtestsuiterun.
CitrusReferenceGuide
505Testsuite
![Page 506: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/506.jpg)
Alsonoticethatwecanrestrictthebeforetestcontainerexecution.Wecanrestrictexecutionbasedonthetestname,package,testgroupsandenvironmentorsystemproperties.Seefollowingexamplehowthisworks:
XMLConfig
<citrus:before-testid="defaultBeforeTest"test="*_Ok_Test"package="com.consol.citrus.longrunning.*"<citrus:actions><citrus-test:echo><citrus-test:message>Thisisexecutedbeforeeachtest!</citrus-test:message></citrus-test:echo></citrus:actions></citrus:before-test>
Theabovebeforetestcomponentisonlyexecutedfortestcasesthatmatchthenamepattern*_Ok_Testandthatmatchthepackagecom.consol.citrus.longrunning.*.Alsowecouldjustusethetestnamepatternorthepackagenamepatternexclusively.Andtheexecutioncanberestrictedbasedontheincludedtestgroupsinourtestsuiterun.Thisenablesustospecifybeforetestactionsinvariousways.Ofcourseyoucanhavemultiplebeforetestconfigurationcomponentsatthesametime.Citruswillpicktherightcontainersandputittoexecutionwhennecessary.
Environmentorsystempropertiesaredefinedaslistofkey-valuepairs.Whenspecifiedthepropertieshavetobepresentwithrespectivevalue.Incasethepropertyvalueisleftoutinconfigurationthepropertymustsimplyexistsonthesysteminordertoenablethebeforesuitesequenceinthattestrun.
XMLConfig
<citrus:before-testid="specialBeforeTest"><citrus:env><citrus:propertyname="USER"/></citrus:env><citrus:system><citrus:propertyname="test-stage"value="e2e"/></citrus:system><citrus:actions><citrus-test:echo><citrus-test:message>Thisisexecutedbeforeeachtest!</citrus-test:message></citrus-test:echo></citrus:actions></citrus:before-test>
CitrusReferenceGuide
506Testsuite
![Page 507: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/507.jpg)
IntheexampleabovethetestsequencewillonlyapplyonenvironmentswithUSERpropertysetandthesystempropertytest-stagemustbesettoe2e.Otherwisethesequenceexecutionisskipped.
WhenusingtheJavaDSLweneedtoimplementthebeforetestlogicinaseparateclassthatextendsTestDesignerBeforeTestSupportorTestRunnerBeforeTestSupport
JavaDSLdesigner
publicclassMyBeforeTestextendsTestDesignerBeforeTestSupport@OverridepublicvoidbeforeTest(TestDesignerdesigner)designer.echo("Thisactionshouldbeexecutedbeforeeachtest");
AsyoucanseetheclassimplementsthemethodbeforeTestthatisprovidedwithatestdesignerargument.YousimplyaddthebeforetestactionstothedesignerinstanceasusualbycallingJavaDSLmethodsonthedesignerobject.Citruswillautomaticallyexecutetheseoperationsbeforeeachtestisexecuted.ThesamelogicappliestothetestrunnervariationthatextendsTestRunnerBeforeTestSupport:
JavaDSLrunner
publicclassMyBeforeTestextendsTestRunnerBeforeTestSupport@OverridepublicvoidbeforeTest(TestRunnerrunner)runner.echo("Thisactionshouldbeexecutedbeforeeachtest");
ThebeforetestimplementationsareaddedtotheSpringbeanapplicationcontextforgeneralactivation.YoucandothiseitherasexplicitSpringbeandefinitionorviapackagecomponent-scan.Hereisasampleforaddingthebeanimplementationexplicitlywithsomeconfiguration
<beanid="myBeforeTest"class="my.company.citrus.MyBeforeTest"><propertyname="packageNamePattern"value="com.consol.citrus.e2e"></property></bean>
CitrusReferenceGuide
507Testsuite
![Page 508: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/508.jpg)
WecanaddfilterpropertiestothebeforetestJavaDSLactionssotheyappliedtospecificpackagesortestnamepatterns.Theaboveexamplewillonlyapplytotestsinpackagecom.consol.citrus.e2e.Leavethesepropertiesemptyfordefaultactionsthatareexecutedbeforealltests.
Aftertest
Thesamelogicthatappliestothebefore-testconfigurationcomponentcanbedoneaftereachtest.Theafter-testconfigurationcomponentdefinestestactionsexecutedaftereachtest.Justlikewepreparedsomedatainactionsbeforeatestwecancleanupthedataafteratesthasfinishedexecution.
XMLConfig
<citrus:after-testid="defaultAfterTest"><citrus:actions><!--listofactionsaftertest--></citrus:actions></citrus:after-test>
Theaftertestconfigurationcomponentreceivesauniqueidandalistoftestactionsthatgetexecutedafteratestcaseisfinished.Noticethattheaftertestactionsareexecutednomatterwhatresultsuccessorfailuretheprevioustestcasecameupto.Thecomponentreceivesusualtestactiondefinitionsjustlikeyouwouldwritetheminanormaltestcasedefinition.Seetheexamplebelowhowtoaddtestactions.
XMLConfig
<citrus:after-testid="defaultAfterTest"><citrus:actions><citrus-test:echo><citrus-test:message>Thisisexecutedaftereachtest!</citrus-test:message></citrus-test:echo></citrus:actions></citrus:after-test>
PleasebeawareofthefactthatwemustusetheCitrustestcaseXMLnamespaceforthenestedtestactiondefinitions.YouhavetodeclaretheXMLnamespacesaccordinglyinyourconfigurationrootelement.Theechotestactionisnowexecutedaftereachtestinourtestsuiterun.Ofcoursewecanrestricttheaftertestcontainerexecution.Supportedrestrictionsarebasedonthetestname,package,testgroupsandenvironmentorsystemproperties.Seefollowingexamplehowthisworks:
CitrusReferenceGuide
508Testsuite
![Page 509: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/509.jpg)
XMLConfig
<citrus:after-testid="defaultAfterTest"test="*_Error_Test"package="com.consol.citrus.error.*"<citrus:actions><citrus-test:echo><citrus-test:message>Thisisexecutedaftereachtest!</citrus-test:message></citrus-test:echo></citrus:actions></citrus:after-test>
Theaboveaftertestcomponentisobviouslyonlyexecutedfortestcasesthatmatchthenamepattern*_Error_Testandthatmatchthepackagecom.consol.citrus.error.*.Alsowecouldjustusethetestnamepatternorthepackagenamepatternexclusively.Andtheexecutioncanberestrictedbasedontheincludedtestgroupsinourtestsuiterun.Thisenablesustospecifyaftertestactionsinvariousways.Ofcourseyoucanhavemultipleaftertestconfigurationcomponentsatthesametime.Citruswillpicktherightcontainersandputittoexecutionwhennecessary.
Environmentorsystempropertiesaredefinedaslistofkey-valuepairs.Whenspecifiedthepropertieshavetobepresentwithrespectivevalue.Incasethepropertyvalueisleftoutinconfigurationthepropertymustsimplyexistsonthesysteminordertoenablethebeforesuitesequenceinthattestrun.
XMLConfig
<citrus:after-testid="specialAfterTest"><citrus:env><citrus:propertyname="USER"/></citrus:env><citrus:system><citrus:propertyname="test-stage"value="e2e"/></citrus:system><citrus:actions><citrus-test:echo><citrus-test:message>Thisisexecutedaftereachtest!</citrus-test:message></citrus-test:echo></citrus:actions></citrus:after-test>
IntheexampleabovethetestsequencewillonlyapplyonenvironmentswithUSERpropertysetandthesystempropertytest-stagemustbesettoe2e.Otherwisethesequenceexecutionisskipped.
CitrusReferenceGuide
509Testsuite
![Page 510: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/510.jpg)
WhenusingtheJavaDSLweneedtoimplementtheaftertestlogicinaseparateclassthatextendsTestDesignerAfterTestSupportorTestRunnerAfterTestSupport
JavaDSLdesigner
publicclassMyAfterTestextendsTestDesignerAfterTestSupport@OverridepublicvoidafterTest(TestDesignerdesigner)designer.echo("Thisactionshouldbeexecutedaftereachtest");
AsyoucanseetheclassimplementsthemethodafterTestthatisprovidedwithatestdesignerargument.YousimplyaddtheaftertestactionstothedesignerinstanceasusualbycallingJavaDSLmethodsonthedesignerobject.Citruswillautomaticallyexecutetheseoperationsaftereachtestisexecuted.ThesamelogicappliestothetestrunnervariationthatextendsTestRunnerAfterTestSupport:
JavaDSLrunner
publicclassMyAfterTestextendsTestRunnerAfterTestSupport@OverridepublicvoidafterTest(TestRunnerrunner)runner.echo("Thisactionshouldbeexecutedaftereachtest");
TheaftertestimplementationsareaddedtotheSpringbeanapplicationcontextforgeneralactivation.YoucandothiseitherasexplicitSpringbeandefinitionorviapackagecomponent-scan.Hereisasampleforaddingthebeanimplementationexplicitlywithsomeconfiguration
<beanid="myAfterTest"class="my.company.citrus.MyAfterTest"><propertyname="packageNamePattern"value="com.consol.citrus.e2e"></property></bean>
WecanaddfilterpropertiestotheaftertestJavaDSLactionssotheyappliedtospecificpackagesortestnamepatterns.Theaboveexamplewillonlyapplytotestsinpackagecom.consol.citrus.e2e.Leavethesepropertiesemptyfordefaultactionsthatareexecutedafteralltests.
CitrusReferenceGuide
510Testsuite
![Page 511: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/511.jpg)
CitrusReferenceGuide
511Testsuite
![Page 512: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/512.jpg)
CustomizemetainformationTestcasesinCitrusareusuallyprovidedwithsomemetainformationliketheauthor’snameorthedateofcreation.InCitrusyouareabletoextendthistestcasemetainformationwithyourownveryspecificcriteria.
Bydefaultatestcasecomesshippedwithmetainformationthatlookslikethis:
<testcasename="PwdChange_OK_1_Test"><meta-info><author>Christoph</author><creationdate>2010-01-18</creationdate><status>FINAL</status><last-updated-by>Christoph</last-updated-by><last-updated-on>2010-01-18T15:00:00</last-updated-on></meta-info>
[...]</testcase>
Youcanquiteeasilyadddatatothissectioninordertomeetyourindividualtestingstrategy.Letushaveasimpleexampletoshowhowitisdone.
FirstofallwedefineacustomXSDschemadescribingthenewelements:
<?xmlversion="1.0"encoding="UTF-8"?><schemaxmlns="http://www.w3.org/2001/XMLSchema"xmlns:tns="http://www.citrusframework.org/samples/my-testcase-info"targetNamespace="http://www.citrusframework.org/samples/my-testcase-info"elementFormDefault="qualified">
<elementname="requirement"type="string"/><elementname="pre-condition"type="string"/><elementname="result"type="string"/><elementname="classification"type="string"/></schema>
Wehavefoursimpleelements(requirement,pre-condition,resultandclassification)alltypedasstring.Thesenewelementslatergointothetestcasemetainformationsection.
CitrusReferenceGuide
512Metainfo
![Page 513: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/513.jpg)
AfterweaddedthenewXMLschemafiletotheclasspathofourprojectweneedtoannouncetheschematoSpring.AsyoumightknowalreadyaCitrustestcaseisnothingelsebutasimpleSpringconfigurationfilewithcustomizedXMLschemasupport.IfweaddnewelementstoatestcaseSpringneedstoknowtheXMLschemaforparsingthetestcaseconfigurationfile.Seethespring.schemasfileusuallyplacedintheMETA-INF/spring.schemasinyourproject.
Thefilecontentforourexamplewilllooklikefollows:
http://www.citrusframework.org/samples/my-testcase-info/my-testcase-info.xsd=com/consol/citrus/schemas/my-testcase-info.xsd
Sonowwearefinallyreadytousethenewmeta-infoelementsinsidethetestcase:
<?xmlversion="1.0"encoding="UTF-8"?><spring:beansxmlns="http://www.citrusframework.org/schema/testcase"xmlns:spring="http://www.springframework.org/schema/beans"xmlns:custom="http://www.citrusframework.org/samples/my-testcase-info"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.citrusframework.org/schema/testcasehttp://www.citrusframework.org/schema/testcase/citrus-testcase.xsdhttp://www.citrusframework.org/samples/my-testcase-infohttp://www.citrusframework.org/samples/my-testcase-info/my-testcase-info.xsd">
<testcasename="PwdChange_OK_1_Test"><meta-info><author>Christoph</author><creationdate>2010-01-18</creationdate><status>FINAL</status><last-updated-by>Christoph</last-updated-by><last-updated-on>2010-01-18T15:00:00</last-updated-on><custom:requirement>REQ10001</custom:requirement><custom:pre-condition>Existinguser,sufficientrights</custom:pre-condition><custom:result>Passwordresetindatabase</custom:result><custom:classification>PasswordChange</custom:classification></meta-info>
[...]</testcase></spring:beans>
NoteWeuseaseparatenamespacedeclarationwithacustomnamespaceprefix“custom”inordertodeclarethenewXMLschematoourtestcase.Ofcourseyoucanpickanamespaceurlandprefixthatfitsbestforyourproject.Asyouseeitisquiteeasy
CitrusReferenceGuide
513Metainfo
![Page 514: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/514.jpg)
toaddcustommetainformationtoyourCitrustestcase.Thecustomizedelementsmaybepreciousforautomaticreporting.XSLtransformationsforinstanceareabletoreadthosemetainformationelementsinordertogenerateautomatictestreportsanddocumentation.
YoucanalsodeclareournewXMLschemaintheEclipsepreferencessectionasuserspecificXMLcatalogentry.TheneventheschemacodecompletioninyourEclipseXMLeditorwillbeavailableforourcustomizedmeta-infoelements.
CitrusReferenceGuide
514Metainfo
![Page 515: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/515.jpg)
Tracingincoming/outgoingmessagesAswedealwithmessagebasedinterfacesCitruswillsendandreceivealotofmessagesduringatestrun.NowwemaywanttoseethesemessagesinchronologicalorderastheywereprocessedbyCitrus.WecanenablemessagetracinginCitrusinordertosavemessagestothefilesystemforfurtherinvestigations.
Citrusoffersaneasywaytodebugallreceivedmessagestothefilesystem.YouneedtoenablesomespecificloggersandinterceptorsintheSpringapplicationcontext.
<beanclass="com.consol.citrus.report.MessageTracingTestListener"/>
JustaddthisbeantotheSpringconfigurationandCitruswilllistenforsentandreceivedmessagesforsavingthosetothefilesystem.Youwillfindfilesliketheseinthedefaulttest-outputfolderafterthetestrun:
Forexample:
logs/trace/messages/MyTest.msgslogs/trace/messages/FooTest.msgslogs/trace/messages/SomeTest.msgs
EachCitrustestwritesa.msgsfilecontainingallmessagesthatwentoverthewireduringthetest.Bydefaultthedebugdirectoryissettologs/trace/messages/relativetotheprojecttestoutputdirectory.Butyoucansetyourownoutputdirectoryintheconfiguration
<beanclass="com.consol.citrus.report.MessageTracingTestListener"><propertyname="outputDirectory"value="file:/path/to/folder"/></bean>
NoteAsthefilenamesdonotchangewitheachtestrunmessagetracingfilesmaybeoverwritten.Soyoueventuallyneedtosavethegeneratedmessagedebugfilesbeforerunninganothergroupoftestcases.
LetsseesomesampleoutputforatestcasewithmessagecommunicationoverSOAPHttp:
SendingSOAPrequest:
CitrusReferenceGuide
515Messagetracing
![Page 516: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/516.jpg)
<?xmlversion="1.0"encoding="UTF-8"?><SOAP-ENV:Envelopexmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"<SOAP-ENV:Header><Operationxmlns="http://citrusframework.org/test">sayHello</Operation></SOAP-ENV:Header><SOAP-ENV:Body><ns0:HelloRequestxmlns:ns0="http://www.consol.de/schemas/samples/sayHello.xsd"><ns0:MessageId>0857041782</ns0:MessageId><ns0:CorrelationId>6915071793</ns0:CorrelationId><ns0:User>Christoph</ns0:User><ns0:Text>HelloWebServer</ns0:Text></ns0:HelloRequest></SOAP-ENV:Body></SOAP-ENV:Envelope>
======================================================================
ReceivedSOAPresponse:<?xmlversion="1.0"encoding="UTF-8"?><SOAP-ENV:Envelopexmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"<SOAP-ENV:Header/><SOAP-ENV:Body><ns0:HelloResponsexmlns:ns0="http://www.consol.de/schemas/samples/sayHello.xsd"><ns0:MessageId>0857041782</ns0:MessageId><ns0:CorrelationId>6915071793</ns0:CorrelationId><ns0:User>WebServer</ns0:User><ns0:Text>HelloChristoph</ns0:Text></ns0:HelloResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>
Forthismessagetracingtoworkweneedtoaddlogginglistenerstooursenderandreceivercomponentsaccordingly.
<citrus-ws:clientid="webServiceClient"request-url="http://localhost:8071"message-factory="messageFactory"interceptors="clientInterceptors"/>
<util:listid="clientInterceptors"><beanclass="com.consol.citrus.ws.interceptor.LoggingClientInterceptor"/></util:list>
ImportantBeawareofaddingtheSpringutilXMLnamespacetotheapplicationcontextwhenusingtheutil:listconstruct.
CitrusReferenceGuide
516Messagetracing
![Page 517: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/517.jpg)
CitrusReferenceGuide
517Messagetracing
![Page 518: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/518.jpg)
ReportingandtestresultsTheframeworkgeneratesdifferentreportsandresultsafteratestrunforyou.Thesereportandresultpageswillhelpyoutogetanoverviewofthetestcasesthatwereexecutedandwhichonewerefailing.
Consolelogging
Duringthetestruntheframeworkwillprovideahugeamountofinformationthatisprintedouttotheconsole.Thisincludescurrenttestprogress,validationresultsanderrorinformation.Thisenablestheusertoquicklysupervisethetestrunprogress.Failuresintestswillbeprintedtotheconsolejustthetimetheerroroccurred.Thedetailedstacktraceinformationandthedetailederrormessagesarehelpfultogettheideawhatwentwrong.
Astheconsoleoutputmightbelimitedtoadefinedbufferlimit,theusermaynotbeabletofollowtheoutputtotheverybeginningofthetestrun.Thereforetheframeworkadditionallyprintsallinformationtoalogfileaccordingtotheloggingconfiguration.
TheloggingmechanismusestheSLF4Jloggingframework.SLF4Jisindependentofloggingframeworkimplementationsonthemarket.SoincaseyouuseLog4Jloggingframeworkthespecifiedlogfilepathaswellaslogginglevelscanbefreelyconfiguredintherespectivelog4j.xmlfileinyourproject.Attheendofatestrunthecombinedtestresultsgetprintedtobothconsoleandlogfile.Theoveralltestresultslooklikefollowingexample:
CITRUSTESTRESULTS
[...]HelloService_Ok_1:SUCCESSHelloService_Ok_2:SUCCESSEchoService_Ok_1:SUCCESSEchoService_Ok_2:SUCCESSEchoService_TempError_1:SUCCESSEchoService_AutomacticRetry_1:SUCCESS[...]
Found175testcasestoexecuteSkipped0testcases(0.0%)Executed175testcasesTestsfailed:0(0.0%)
CitrusReferenceGuide
518Reporting
![Page 519: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/519.jpg)
Testssuccessfully:175(100.0%)
Failedtestswillbemarkedasfailedintheresultlist.Theframeworkwillgiveashortdescriptionoftheerrorcausewhilethedetailedstacktraceinformationcanbefoundinthelogmessagesthatweremadeduringthetestrun.
HelloService_Ok_3:failed-ExceptionisActiontimedout
JUnitreports
AstestsareexecutedasTestNGtestcases,theframeworkwillalsogenerateJUnitcompliantXMLandHTMLreports.JUnittestreportsareverypopularandfindsupportinmanybuildmanagementanddevelopmenttools.IngeneraltheCitrustestreportsgiveyouanoverallpictureofalltestsandtellyouwhichofthemwerefailing.
BuildmanagementtoolslikeJenkinscaneasilyimportanddisplaythegeneratedJUnitXMLresults.PleasehavealookattheTestNGandJUnitdocumentationformoreinformationaboutthistopicaswellasthebuildmanagementtools(e.g.Jenkins)tofindouthowtointegratethetestsresults.
HTMLreports
CitruscreatesHTMLreportsaftereachtestrun.Thereportprovidesdetailedinformationonthetestrunwithasummaryofalltestresults.Youcanfindthereportafteratestruninthedirectory$project.build.directory/test-output/citrus-reports.
Thereportconsistsoftwoparts.Thetestsummaryontopshowsthetotalnumberexecutedtests.Themainpartlistsalltestcaseswithdetailedinformation.Withthisreportyouimmediatelyidentifyallteststhatwerefailing.Eachtestcaseismarkedincoloraccordingtoitsresultoutcome.
ThefailedtestsgivedetailederrorinformationwitherrormessagesandJavaStackTraceinformation.InadditiontothatthereporttriestofindthetestactioninsidetheXMLtestpartthatfailedinexecution.Withthefailingcodesnippetyoucanseewheretheteststopped.
NoteJavaScriptshouldbeactiveinyourwebbrowser.Thisistoenablethedetailedinformationwhichcomestoyouinformoftooltipsliketestauthorordescription.IfyouwanttoaccessthetooltipsJavaScriptshouldbeenabledinyourbrowser.
CitrusReferenceGuide
519Reporting
![Page 520: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/520.jpg)
TheHTMLreportsarecustomizablebysystemproperties.Usefollowingpropertiese.g.inyourcitrus.propertiesfile:
citrus.html.report.enabled:Enables/disablesHTMLreportgeneration(default=true).citrus.html.report.directory:Outputdirectorypath(default=$project.build.directory/test-output/citrus-reports).citrus.html.report.file:Filenameforthereportfile(default=citrus-test-results.html).citrus.html.report.template:TemplateHTMLfilewithplaceholdersforreportresults.citrus.html.report.detail.template:Templatefilefordetailedtestresults.citrus.html.report.logo:FileresourcepathpointingtoaimagethatisaddedtotopofHTMLreport.
TheHTMLreportisbasedonatemplatefilethatiscustomizabletoyourspecialneeds.Thedefaulttemplatescanbefoundinreport-templatessources.
CitrusReferenceGuide
520Reporting
![Page 521: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/521.jpg)
SamplesThischaptergivessomesampleswhereyoucanseeCitrusinaction.
samples-flightbooking
CitrusReferenceGuide
521Samples
![Page 522: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/522.jpg)
TheFlightBookingsample
AsimpleprojectexampleshouldgiveyoutheideahowCitrusworks.Thesystemundertestisaflightbookingservicethathandlestravelrequestsfromatravelagency.Atravelrequestconsistsofacompletetravelrouteincludingseveralflights.TheFlightBookingServiceapplicationwillsplitthecompletetravelbookingintoseparateflightbookingsthataresenttotherespectiveairlinesincharge.Thebookingandcustomerdataispersistedinadatabase.
Theairlineswillconfirmordenytheflightbookings.TheFlightBookingServiceapplicationconsolidatesallincomingflightconfirmationsandcombinesthemtoacompletetravelconfirmationordenialthatissentbacktothetravelagency.Nextpicturetriestoputthearchitectureintographics:
InourexampletwodifferentairlinesareconnectedtotheFlightBookingServiceapplication:theSmartArilineoverJMSandtheRoyalAirlineoverHttp.
Theusecase
Theusecasethatwewouldliketotestisquitesimple.Thetestshouldhandleasimpletravelbookingandexpectapositiveprocessingtotheend.Thetestcaseneithersimulatesbusinesserrorsnortechnicalproblems.Nextpictureshowstheusecaseasasequencediagram.
CitrusReferenceGuide
522FlightBookingSample
![Page 523: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/523.jpg)
Thetravelagencyputsatravelbookingrequesttowardsthesystem.Thetravelbookingcontainstwoseparateflights.Theflightrequestsarepublishedtotheairlines(SmartAirlineandRoyalAirline).Bothairlinesconfirmtheflightbookingswithapositiveanswer.Theconsolidatedtravelbookingresponseisthensentbacktothetravelagency.
Configurethesimulatedsystems
Citrussimulatesallsurroundingapplicationsintheirbehaviorduringthetest.Thesimulatedapplicationsare:TravelAgency,SmartAirlineandRoyalAirline.ThesimulatedsystemshavetobeconfiguredintheCitrusconfigurationfirst.TheconfigurationisdoneinSpringXMLconfigurationfiles,asCitrususesSpringtoglueallitsservicestogether.
FirstofallwehavealookattheTravelAgencyconfiguration.TheTravelAgencyisusingJMStoconnecttoourtestedsystem,soweneedtoconfigurethisJMSconnectioninCitrus.
<beanname="connectionFactory"class="org.apache.activemq.ActiveMQConnectionFactory"><propertyname="brokerURL"value="tcp://localhost:61616"/></bean>
<citrus-jms:endpointid="travelAgencyBookingRequestEndpoint"destination-name="$travel.agency.request.queue"/>
<citrus-jms:endpointid="travelAgencyBookingResponseEndpoint"destination-name="$travel.agency.response.queue"/>
CitrusReferenceGuide
523FlightBookingSample
![Page 524: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/524.jpg)
ThisisallCitrusneedstosendandreceivemessagesoverJMSinordertosimulatetheTravelAgency.BydefaultallJMSmessagesendersandreceiversneedaconnectionfactory.ThereforeCitrusissearchingforabeannamed"connectionFactory".IntheexampleweconnecttoaActiveMQmessagebroker.AconnectiontootherJMSbrokerslikeTIBCOEMSorApacheActiveMQispossibletoobysimplychangingtheconnectionfactoryimplementation.
Theidentifiersofthemessagesendersandreceiversareveryimportant.Weshouldthinkofsuitableidsthatgivethereaderafirsthintwhatthesender/receiverisusedfor.AswewanttosimulatetheTravelAgencyincombinationwithsendingbookingrequestsouridis"travelAgencyBookingRequestEndpoint"forexample.
ThesenderandreceiversdoalsoneedaJMSdestination.Herethedestinationnamesareprovidedbypropertyexpressions.TheSpringIoCcontainerresolvesthepropertiesforus.AllweneedtodoispublishthepropertyfiletotheSpringcontainerlikethis.
<beanname="propertyLoader"class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"><propertyname="locations"><list><value>citrus.properties</value></list></property><propertyname="ignoreUnresolvablePlaceholders"value="true"/></bean>
Thecitrus.propertiesfileislocatedinourproject'sresourcesfolderanddefinestheactualqueuenamesbesidesotherpropertiesofcourse:
#JMSqueuestravel.agency.request.queue=Travel.Agency.Request.Queuetravel.agency.response.queue=Travel.Agency.Response.Queuesmart.airline.request.queue=Smart.Airline.Request.Queuesmart.airline.response.queue=Smart.Airline.Response.Queueroyal.airline.request.queue=Royal.Airline.Request.Queue
WhatelsedoweneedinourSpringconfiguration?TherearesomebasicbeansthatarecommonlydefinedinaCitrusapplicationbutIdonotwanttoboreyouwiththesedetails.SoifyouwanttohavealookattheSpringapplicationcontextfileintheresourcesfolderandseehowthingsaredefinedthere.
CitrusReferenceGuide
524FlightBookingSample
![Page 525: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/525.jpg)
WecontinuewiththefirstairlinetobeconfiguredtheSmartAirline.TheSmartAirlineisalsousingJMStocommunicatewiththeFlightBookingService.Sothereisnothingnewforus,wesimplydefineadditionalJMSmessagesendersandreceivers.
<citrus-jms:endpointid="smartAirlineBookingRequestEndpoint"destination-name="$smart.airline.request.queue"/>
<citrus-jms:endpointid="smartAirlineBookingResponseEndpoint"destination-name="$smart.airline.response.queue"/>
WedonotdefineanewJMSconnectionfactorybecauseTravelAgencyandSmartAirlineareusingthesamemessagebrokerinstance.Incaseyouneedtohandlemultipleconnectionfactoriessimplydefinetheconnectionfactorywiththeattribute"connection-factory".
<citrus-jms:endpointid="smartAirlineBookingRequestEndpoint"destination-name="$smart.airline.request.queue"connection-factory="smartAirlineConnectionFactory"/>
<citrus-jms:endpointid="smartAirlineBookingResponseEndpoint"destination-name="$smart.airline.response.queue"connection-factory="smartAirlineConnectionFactory"/>
ConfiguretheHttpadapter
TheRoyalAirlineisconnectedtooursystemusingHttprequest/responsecommunication.ThismeanswehavetosimulateaHttpserverinthetestthatacceptsclientrequestsandprovidesproperresponses.CitrusoffersaHttpserverimplementationthatwilllistenonaportforclientrequests.TheadapterforwardsincomingrequesttothetestengineoverJMSandreceivesaproperresponsethatisforwardedasaHttpresponsetotheclient.Thenextpictureshowsthismechanismindetail.
TheRoyalAirlineadapterreceivesclientrequestsoverHttpandsendsthemoverJMStoamessagereceiveraswealreadyknowit.Thetestenginevalidatesthereceivedrequestandprovidesaproperresponsebacktotheadapter.Theadapterwilltransform
CitrusReferenceGuide
525FlightBookingSample
![Page 526: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/526.jpg)
theresponsetoHttpagainandpublishesittothecallingclient.CitrusoffersthesekindofadaptersforHttpandSOAPcommunication.BywritingyourownadapterslikethisyouwillbeabletoextendCitrussoitworkswithprotocolsthatarenotsupportedyet.
LetusdefinetheHttpadapterintheSpringconfiguration:
<citrus-http:serverid="royalAirlineHttpServer"port="8091"uri="/flightbooking"endpoint-adapter="jmsEndpointAdapter"/>
<citrus-jms:endpoint-adapterid="jmsEndpointAdapterdestination-name="$royal.airline.request.queue"/>connection-factory="connectionFactory"/>timeout="2000"/>
<citrus-jms:sync-endpointid="royalAirlineBookingEndpoint"destination-name="$royal.airline.request.queue"/>
WeneedtoconfigureaHttpserverinstancewithaport,arequestURIandtheendpointadapter.WedefinetheJMSendpointadaptertohandlerequestasdescribed.InAdditiontotheendpointadapterwealsoneedsynchronousJMSmessagesenderandreceiverinstances.That'sit!WeareabletoreceiveHttprequestinordertosimulatetheRoyalAirlineapplication.Whatismissingnow?Thetestcasedefinitionitself.
Thetestcase
ThetestcasedefinitionisalsoaSpringconfigurationfile.CitrusoffersacustomizedXMLsyntaxtodefineatestcase.ThisXMLtestdefininglanguageissupposedtobeeasytounderstandandmorespecifictothedomainwearedealingwith.Nextlistingshowsthewholetestcasedefinition.Keepinmindthatatestcasedefineseverystepintheusecase.Sowedefinesendingandreceivingactionsoftheusecaseasdescribedinthesequencediagramwesawearlier.
<?xmlversion="1.0"encoding="UTF-8"?><spring:beansxmlns="http://www.citrusframework.org/schema/testcase"xmlns:spring="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.citrusframework.org/schema/testcasehttp://www.citrusframework.org/schema/testcase/citrus-testcase.xsd"><testcasename="FlightBookingTest"><meta-info>
CitrusReferenceGuide
526FlightBookingSample
![Page 527: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/527.jpg)
<author>ChristophDeppisch</author><creationdate>2009-04-15</creationdate><status>FINAL</status><last-updated-by>ChristophDeppisch</last-updated-by><last-updated-on>2009-04-15T00:00:00</last-updated-on></meta-info><description>Testflightbookingservice.</description><variables><variablename="correlationId"value="citrus:concat('Lx1x','citrus:randomNumber(10)')"/><variablename="customerId"value="citrus:concat('Mx1x',citrus:randomNumber(10))"/></variables><actions><sendendpoint="travelAgencyBookingRequestEndpoint"><message><data><![CDATA[<TravelBookingRequestMessagexmlns="http://www.consol.com/schemas/TravelAgency"><correlationId>$correlationId</correlationId><customer><id>$customerId</id><firstname>John</firstname><lastname>Doe</lastname></customer><flights><flight><flightId>SM1269</flightId><airline>SmartAirline</airline><fromAirport>MUC</fromAirport><toAirport>FRA</toAirport><date>2009-04-15</date><scheduledDeparture>11:55:00</scheduledDeparture><scheduledArrival>13:00:00</scheduledArrival></flight><flight><flightId>RA1780</flightId><airline>RoyalAirline</airline><fromAirport>FRA</fromAirport><toAirport>HAM</toAirport><date>2009-04-15</date><scheduledDeparture>16:00:00</scheduledDeparture><scheduledArrival>17:10:00</scheduledArrival></flight></flights></TravelBookingRequestMessage>]]></data></message>
CitrusReferenceGuide
527FlightBookingSample
![Page 528: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/528.jpg)
<header><elementname="correlationId"value="$correlationId"/></header></send>
<receiveendpoint="smartAirlineBookingRequestEndpoint"><message><data><![CDATA[<FlightBookingRequestMessagexmlns="http://www.consol.com/schemas/AirlineSchema"><correlationId>$correlationId</correlationId><bookingId>???</bookingId><customer><id>$customerId</id><firstname>John</firstname><lastname>Doe</lastname></customer><flight><flightId>SM1269</flightId><airline>SmartAirline</airline><fromAirport>MUC</fromAirport><toAirport>FRA</toAirport><date>2009-04-15</date><scheduledDeparture>11:55:00</scheduledDeparture><scheduledArrival>13:00:00</scheduledArrival></flight></FlightBookingRequestMessage>]]></data><ignorepath="//:FlightBookingRequestMessage/:bookingId"/></message><header><elementname="correlationId"value="$correlationId"/></header><extract><messagepath="//:FlightBookingRequestMessage/:bookingId"variable="$smartAirlineBookingId"/></extract></receive>
<sendendpoint="smartAirlineBookingResponseEndpoint"><message><data><![CDATA[<FlightBookingConfirmationMessagexmlns="http://www.consol.com/schemas/AirlineSchema"><correlationId>$correlationId</correlationId><bookingId>$smartAirlineBookingId</bookingId><success>true</success><flight><flightId>SM1269</flightId>
CitrusReferenceGuide
528FlightBookingSample
![Page 529: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/529.jpg)
<airline>SmartAirline</airline><fromAirport>MUC</fromAirport><toAirport>FRA</toAirport><date>2009-04-15</date><scheduledDeparture>11:55:00</scheduledDeparture><scheduledArrival>13:00:00</scheduledArrival></flight></FlightBookingConfirmationMessage>]]></data></message><header><elementname="correlationId"value="$correlationId"/></header></send>
<receiveendpoint="royalAirlineBookingEndpoint"><message><data><![CDATA[<FlightBookingRequestMessagexmlns="http://www.consol.com/schemas/FlightBooking/AirlineSchema"><correlationId>$correlationId</correlationId><bookingId>???</bookingId><customer><id>$customerId</id><firstname>John</firstname><lastname>Doe</lastname></customer><flight><flightId>RA1780</flightId><airline>RoyalAirline</airline><fromAirport>FRA</fromAirport><toAirport>HAM</toAirport><date>2009-04-15</date><scheduledDeparture>16:00:00</scheduledDeparture><scheduledArrival>17:10:00</scheduledArrival></flight></FlightBookingRequestMessage>]]></data><ignorepath="//:FlightBookingRequestMessage/:bookingId"/></message><header><elementname="correlationId"value="$correlationId"/></header><extract><messagepath="//:FlightBookingRequestMessage/:bookingId"variable="$royalAirlineBookingId"/></extract></receive>
CitrusReferenceGuide
529FlightBookingSample
![Page 530: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/530.jpg)
<sendendpoint="royalAirlineBookingEndpoint"><message><data><![CDATA[<FlightBookingConfirmationMessagexmlns="http://www.consol.com/schemas/AirlineSchema"><correlationId>$correlationId</correlationId><bookingId>$royalAirlineBookingId</bookingId><success>true</success><flight><flightId>RA1780</flightId><airline>RoyalAirline</airline><fromAirport>FRA</fromAirport><toAirport>HAM</toAirport><date>2009-04-15</date><scheduledDeparture>16:00:00</scheduledDeparture><scheduledArrival>17:10:00</scheduledArrival></flight></FlightBookingConfirmationMessage>]]></data></message><header><elementname="correlationid"value="$correlationId"/></header></send>
<receiveendpoint="travelAgencyBookingResponseEndpoint"><message><data><![CDATA[<TravelBookingResponseMessagexmlns="http://www.consol.com/schemas/TravelAgency"><correlationId>$correlationId</correlationId><success>true</success><flights><flight><flightId>SM1269</flightId><airline>SmartAirline</airline><fromAirport>MUC</fromAirport><toAirport>FRA</toAirport><date>2009-04-15</date><scheduledDeparture>11:55:00</scheduledDeparture><scheduledArrival>13:00:00</scheduledArrival></flight><flight><flightId>RA1780</flightId><airline>RoyalAirline</airline><fromAirport>FRA</fromAirport><toAirport>HAM</toAirport><date>2009-04-15</date><scheduledDeparture>16:00:00</scheduledDeparture>
CitrusReferenceGuide
530FlightBookingSample
![Page 531: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/531.jpg)
<scheduledArrival>17:10:00</scheduledArrival></flight></flights></TravelBookingResponseMessage>]]></data></message><header><elementname="correlationId"value="$correlationId"/></header></receive>
</actions></testcase></spring:beans>
Similartoasequencediagramthetestcasedescribeseverystepoftheusecase.Attheverybeginningthetestcasegetsnameanditsmetainformation.Followingwiththevariablevaluesthatareusedalloverthetest.HereitisthecorrelationIdandthecustomerIdthatareusedastestvariables.Insidemessagetemplatesheadervaluesthevariablesarereferencedseveraltimesinthetest
<correlationId>$correlationId</correlationId><id>$customerId</id>
Thesending/receivingactionsuseapreviouslydefinedmessagesender/receiver.ThisisthelinkbetweentestcaseandbasicSpringconfigurationwehavedonebefore.
sendendpoint="travelAgencyBookingRequestEndpoint"
Thesendingactionchoosesamessagesendertoactuallysendthemessageusingamessagetransport(JMS,Http,SOAP,etc.).Aftersendingthisfirst"TravelBookingRequestMessage"requestthetestcaseexpectsthefirst"FlightBookingRequestMessage"messageontheSmartAirlineJMSdestination.Incasethismessageisnotarrivingintimethetestwillfailwitherrors.InpositivecaseourFlightBookingServiceworkswellandthemessagearrivesintime.Thereceivedmessageisvalidatedagainstadefinedexpectedmessagetemplate.Onlyincaseallcontentvalidationstepsaresuccessfulthetestcontinueswiththeactionchain.Andsothetestcaseproceedsandworksthroughtheusecaseuntileverymessageissentrespectivelyreceivedandvalidated.Theusecaseisdoneautomaticallywithouthumaninteraction.Citrussimulatesallsurroundingapplicationsandprovidesdetailedvalidationpossibilitiesofmessages.
CitrusReferenceGuide
531FlightBookingSample
![Page 532: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/532.jpg)
CitrusReferenceGuide
532FlightBookingSample
![Page 533: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/533.jpg)
AppendixThischaptergivesabriefoverviewofallarchivedchanges.
Changes2.5Changes2.4Changes2.3Changes2.2Changes2.1Changes2.0Changes1.4Changes1.3Changes1.2
CitrusReferenceGuide
533Appendix
![Page 534: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/534.jpg)
ChangesinCitrus2.6Citrus2.6comeswithasetofnewmodulesthatenablecompletelynewaspectsofintegrationtesting.NamelythesearethenewmodulesforCucumberbehaviordrivendevelopmentandZookeepersupport.Justhavealookatthefollowingfeaturesthatareshippedwithinthe2.6box.
Gzipcompression
CitrusnowsupportsGzipmessagecompression.ForHttpclientserverendpointsweintroducedspecialcompressionfiltersthatautomaticallytakcareoncompressionwhenthehttpheaderAccept-Encoding=gziporContent-Encoding=gzipisset.Forotherendpointsweintroducedthemessagetypegzipandthemessagevalidatorgzip-base64whichautomaticallycompressesanddecompressesmessagepayloadsandenablesbase64Stringcomparisonforvalidationpurpose.Thenewcompressionfeaturesaredescribedinhttpandvalidation-gzip.
Customservletfilters
TheCitrushttpservercomponentnowacceptscustomservletfilterimplementations.Thisisusefulforimplementingcustomlogiconrequest/responseprocessingsuchasautomaticmessagecompressionorcaching.Youcansetoneormanycustomfilterimplementationsandmapthosetorequestpathsfortheserver.Readaboutthisinchapterhttp.
Escapetestvariablesyntax
Citrususestestvariablesandlooksfortheexpressionsoftype$variable-name.NowwhenthissamesyntaxispartofamessagecontentwerunintoerrorsasCitruswantstofindatestvariable.AttheendCitruscomplainsabouttheunknownvariable.ThereforeweintroducedanescapesyntaxforvariablessoyoucanskiptheCitrusvariableexpressionevaluation.Youcandothisbyusing$//escaped//syntax.Readmoreaboutthisintest-variables.
ConfigurableXMLserializer
CitrusReferenceGuide
534Changes2.6
![Page 535: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/535.jpg)
WeoftendealwithXMLmessageformatandthereforeneedtoparseandserializeXMLdata.ThedefaultXMLserializerusesprettyprintformatandcdatasectionsupport.Nowsometimesitismandatorytocustomizethesesettingswhichispossiblewiththenewversion.YoucanaddacustomXMLserializerintheSpringapplicationcontextandCitruswillautomaticallyusethisimplementationandconfiguration.Youcanseehowitworksinchaptervalidation-xml.
Localmessagestore
Weintroducedalocalmessagestorethatautomaticallysavesallexchangedmessages(inboundandoutbound).Thismessagestorecanbeusedtogetexchangedmessagesduringandafterthetest.Testactionsaswellastestlistenerscanaccessthelocalmessagestore.Readmoreaboutthisinchaptersendpoints,actions-sendandactions-receive.
Waitmessagecondition
Thewaittestactionhasanewcondition.Besideswaitingforfilestoexistandhttprequeststoberespondedyoucannowwaitformessagesinthelocalmessagestore.Thiswayyoucanwaitforacertainmessagetoarrive.Thisisdescribedinchapteractions-wait.
XpathandJsonPathFunction
TherearenewfunctionsavailabletoevaluatesomeXpathorJsonPathexpressiononaXML/Jsonsource.Thesourcecanbeastaticstructurecomingfromanexternalfileoramessagepayloadstoredinthelocalstorage.Seehowtousethisfunctionsinchapterfunctions.
Staticresponseadaptervariablessupport
Servercomponentscanusestaticresponseadaptersthatautomaticallysendresponsemessagestoanycallingclient.Theresponseadapterisnowabletousetestvariablesandfunctions.InadditiontothatyoucanmapvaluesfromtheactualrequestmessagethathastriggeredtheresponseadapterbyusingthelocalmessagestoreincombinationwithXpathorJsonPath.Readaboutthisinendpoint-adapter.
CucumberBDDsupport
CitrusReferenceGuide
535Changes2.6
![Page 536: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/536.jpg)
Behaviordrivendevelopmentismoreandmorecomingupalsointheintegrationtestingenvironment.CucumberisafantasticbehaviordrivendevelopmentlibrarythatprovidessupportforBDDconceptswithGherkin.ThenewCitrusintegrationwithCucumberenablesthemixofGherkinsyntaxfeaturescenarioswithCitrustestcaseexecution.YouwritefeaturestoriesasusualandcreateCitrustestcaseswithlotsofactionsfortheintegrationtest.Seedetailsforthisfeatureincucumber.
Zookeepersupport
ZookeeperfromApacheletsyoumanageconfigurationwithdistributedcoordination.AsauseryoucreateandeditvaluesonaZookeeperserver.Otherclientsthencanretrievethisinformation.WithCitrusyouareabletoaccessthisinformationfromwithinatestcase.TheZookeeperCitrusclientletsyoumanageinformationontheZookeeperserver.Seedetailsforthisfeatureinzookeeper.
SpringRestdocssupport
RestdocsisafantasticwayofgeneratingdocumentationforRESTfulAPIs.Whileexchangingrequest/responsedatawiththeserverRestdocscreatesdocumentationinformationonthedata.Thedocumentationincludesfielddescriptions,headersandsnippetsforbodycontent.WithnewCitrusversionHttpclientsinCitruscanaddRestdocinterceptorsthatgeneratethedocumentationwhileexecutingthetestcases.Thiswayyouareabletodocumentwhatmessageswereexchangedintests.TheRestdocssupportisalsoavailablefortheSOAPHttpclientinCitrus.Seedetailsinrestdocs.
Hamcrestmatcherconditions
IteratingtestactioncontainersinCitrusevaluatebooleanexpressionsfordeterminationofhowtoexecutethenestedactionsinaloop.Alsotheconditionalcontainerexecutesnestedactionsbasedonbooleanexpressionevaluation.TheCitrusbooleanexpressionsupportislimitedtoverybasicoperationssuchaslowerthanorgreaterthan.Furthermorethecombinationofbooleanexpressionswithvariableshasnotbeensupported.FollowingfromthatwehaveimprovedthebooleanexpressionevaluationmechanismwithextensiontoHamcrestmatchers.Sonowyoucanevaluatematchersiniteratingconditions.Thisfeatureisdescribedincontainers-conditionalandcontainers-iterate.
SOAPJavaDSL
CitrusReferenceGuide
536Changes2.6
![Page 537: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/537.jpg)
CitrusprovidesanewJavafluentAPIforsendingandreceivingSOAPrelatedmessagecontent.TheJavaDSLenhancementsarebasedonthoseofHttp.NowyoucandefineSOAPmessageswithspecialSOAPactionheadersmoreeasily.OntopofthatyoucanhandleSOAPfaultsonclientandserverwiththefluentAPI.Checkoutsoap-webservicesfordetails.
Refactoring
Refactoringintermsofsimplificationandstandardizationispartofourdailylifeasadeveloper.WehavebeenworkingonimprovingtheJavaDSLfluentAPIforSOAP.Wealsointroducedamorecommonwayofhandlingthetestactioncontainerslikeiterate,parallelandsoon.Thisleadstosomeclassesandmethodsthatweremarkedasdeprecated.SopleasehavealookatyourJavaDSLcodeandifyouseesomeusageofdeprecatedstuffpleaseusethenewapproachesassoonaspossible.Thedeprecatedstuffwilldefinitelydisappearinupcomingreleases.
Someofthechangesthatwehavemademighthityourightaway.Thesechangesare:
ws:assertelementinSOAPtestcaseschemahasbeenrenamedtows:assert-fault.Thiswasdoneforbetterinteroperabilityreasonswithassertactionincoreschemaandtobecomplianttosend-faultaction.
JavaDSLmodulehashadMavendependenciestoseveralothermodulesinCitrus(e.g.citrus-jms,citrus-soap).Thesedependenciesweredeclaredascompiledependencies,whichisnotveryniceasyoumightnotneedJMSorSOAPfunctionalitiesinyourproject.Wehaveaddedoptionalandprovidedmarkerstothatdependencieswhichmeansthatyouhavetodecideinyourprojectwhichofthemodulestoinclude.
YoumayfacesomemissingdependencieserrorswhenrunningtheMavenproject.AsaresultyouneedtoincludetheCitrusmodules(e.g.citrus-http,citrus-docker,andsoon)inyourprojectMavenPOMexplicitly.
CitrusReferenceGuide
537Changes2.6
![Page 538: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/538.jpg)
ChangesinCitrus2.5WehaveaddedlotsofnewfeaturesandimprovementswithCitrus2.5.NamelythesearethenewmodulesforRMIandJMXsupport,anewx-www-form-urlencodedmessagevalidatorandnewfunctionsanctestactions.Justhavealookatthefollowingfeaturesthatmadeittothebox.
Hamcrestmatchersupport
Hamcrestisaverypowerfulmatcherlibrarythatprovidesafantasticsetofmatcherimplementationsformessagevalidationpurpose.CitrusnowsupportsthesematcherscomingfromHamcrestlibrary.OntheonehandyoucanuseHamcrestmatchersasaCitrusvalidationmatcherasdescribedinvalidation-matcher-hamcrest.OntheotherhandyoucanuseHamcrestmatchersnowdirectlyusingtheCitrusJavaDSL.Seedetailsforthisfeatureinjson-path-validate.
Binarybase64messagevalidator
Thereisanewmessagevalidatorimplementationthatautomaticallyconvertsbinarymessagecontenttoabase64encodedStringrepresentationforcomparison.Thisistheeasiestwaytocomparebinarymessagecontentwithanexpectedmessagepayload.Seevalidation-binaryhowthisisworkingforyou.
RMIsupport
RemotemethodinvocationisastandardJavatechnologyandAPIforcallingmethodsonremoteobjectsacrossdifferentJVMinstances.AlthoughRMIhaslostitspopularityitisstillusedinlegacycomponents.TestingRMIbeaninvocationisahardthingtodo.NowCitrusprovidesclientandserversupportforremoteinterfaceinvocation.Seermifordetails.
JMXsupport
SimilartoRMIJMXcanbeusedtoconnecttoremotebeaninvocation.ThistimeweexposesomebeanstoamanagedbeanserverinordertobemanagedbyJMXoperationsforreadandwrite.WithCitrus2.5wehaveaddedaclientandserversupportforcallingandprovidingmanagedbeansonambeanserver.Seejmxfordetails.
CitrusReferenceGuide
538Changes2.5
![Page 539: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/539.jpg)
Resourceinjection
With2.5wehaveaddedmechanismsforinjectingCitruscomponentstoyourJavaDSLtestmethods.ThisisveryusefulwhenneedingaccesstotheCitrustestcontextforinstance.Alsoweareabletousenewinjectionoftestdesignerandrunnerinstancesinordertosupportparalleltestexecutionwithmultiplethreads.Seetheexplanationsintestcase-resource-injectionandtestcase-context-injection.
Httpx-www-form-urlencodedmessagevalidator
HTMLformdatacanbetransmittedwithdifferentmethodsandcontenttypes.Oneofthemostcommonwaysistousex-www-form-urlencodedformdatacontent.Asvalidationcanbetrickywehaveaddedaspecialmessagevalidatorforthat.Seehttp-www-form-urlencodedfordetails.
Daterangevalidationmatcher
Addedanewvalidationmatcherimplementationthatisabletocheckthatadatevalueisbetweenacertaindaterange(fromandto)Thedaterangeisabletofocusondaysaswellasadditionaltime(hour,minute,second)specifications.Seevalidation-matcher-daterangefordetails.
Readfileresourcefunction
Anewfunctionimplementationoffersyouthepossibilitiestoreadfileresourcecontentsasinlinedata.Thefunctioniscalledandreturnsthefilecontentasreturnvalue.Thefilecontentisthenplacedrightwherethefunctionwascallede.g.insideofamessagepaylaodelementorasmessageheadervalue.Seefunctions-read-filefordetails.
Timercontainer
Thenewtimertestactioncontainerrepeatsitsexecutionbasedonatimeexpression(e.g.every5seconds).Withthistimerwecanrepeattestactionswithafixedtimedelayorconstantlyexecutetestactionswithtimeschedule.Seecontainers-timerandactions-stop-timerfordetails.
UpgradetoVert.x3.2.0
CitrusReferenceGuide
539Changes2.5
![Page 540: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/540.jpg)
TheVert.xmodulewasupgradedtouseVert.x3.2.0version.TheCitrusmoduleimplementationwasupdatedtoworkwiththisnewVert.xversion.LearnmoreabouttheVert.xintegrationinCitruswithvertx.
CitrusReferenceGuide
540Changes2.5
![Page 541: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/541.jpg)
ChangesinCitrus2.4Citrus2.4comeswithasetofnewfeaturesespeciallyregardingApacheCamelandDockerintegrations.Bugfixesofcoursearealsopartofthepackage.Seethefollowingoverviewonwhathaschanged.
Dockersupport
DockerandMicroservicesarefrequenttopicsinsoftwaredevelopmentrecently.WehaveaddedinteractionwithDockerinCitrussotheusercanmanageDockercontainerswithinatestcase.CitrusnowprovidesspecialDockertestactionsforbuilding,starting,stoppingandinspectingDockerimagesandcontainersinatest.Seedockerfordetails.
HttpRESTactions
WehavesignificantlyimprovedtheHttpRESTsupportinCitrus.ThefocusisonsimplifyingtheHttpRESTusageinCitrustestcases.WithnewHttpspecifictestactionsonclientandserverwecansendandreceiveHttpRESTmessagesveryeasy.Seehttpfordetails.
Waittestaction
Withthenewwaittestactionwecanexplicitlywaitforsomeremoteconditiontobecometrueinsideofatestcase.TheconditionssupportedatthemomentareHttpurlrequestsandfilebasedconditions.AusercaninvokeaHttpserverurlandwaitforittoreturnasuccessHttp200OKresponse.Thisisanawesomefeaturewhenwaitingforaservertostartupbeforethetestcontinues.WecanalsothinkofwaitingforaDockercontainertostartupbeforecontinuing.Oryoucanwaituntilafileispresentonthelocalfilesystem.Seeactions-waitfordetails.
Camelactions
CitrushasalreadyhadsupportforApacheCamelroutesandCamelcontextloading.Nowwith2.4versionwehaveaddedsomespecialApacheCameltestactionsforinteractingwithaCamelcontextanditsroutes.ThisenablesthetestertocreateanduseanewCamelrouteontheflyinsideatestcase.AlsoCitrusisnowabletointeractwith
CitrusReferenceGuide
541Changes2.4
![Page 542: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/542.jpg)
theCamelcontrolbusaccessingroutestatisticsandstatusinformation.Alsopossiblearestart,stop,suspend,resumeoperationsonaCamelroute.Seecamel-actionsandcamel-controlbusfordetails.
Purgeendpointsaction
PurgingJMSqueuesandinmemorychannelsattestruntimehasbecomeawidelyusedfeatureespeciallywhenaimingtomaketestsmorestableintermsofindependenttests.Wehaveaddedapurgeendpointtestactionthatworksonanyconsumerendpoint.Soyoudonotneedtoseparatebetweenendpointimplementationsanymoreandmoreimportantyoucanpurgeserverinmemorychannelcomponentsveryeasy.Seeactions-purge-endpointsfordetails.
ReleasetoMavenCentral
Thisisnotanewfeaturebutalsoworthtotellhereasitisasignificantimprovementonthewholeframeworkproject.WecannowreleasetheCitrusartifactstoMavencentralrepository.Soyoudonotneedtheadditionallabs.consol.derepositoryinyourMavenPOManymore.Thelabs.consol.derepositorywillcontinuetoexistthoughaswewillreleaseSNAPSHOTversionsofCitrushereinfuture.
CitrusReferenceGuide
542Changes2.4
![Page 543: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/543.jpg)
ChangesinCitrus2.3WewanttogiveyouashortoverviewofwhathaschangedinCitrus2.3.Thereleaseaddssomenewfeaturesandimprovementstothebox.Bugfixesofcoursearealsopartofthepackage.Seethefollowingoverviewonwhathaschanged.
Testrunnerandtestdesigner
OneofthebiggestissueswiththeCitrusJavaDSListhefactthattheCitrusJavaDSLmethodsfirstbuildthewholetestcasetogetherbeforetheactualexecutiontakesplace.SocallingaJavaDSLmethodsendforinstancejustpreparesthesendingtestaction.Theactualsendingofthemessagetakesplacetoalatertimewhenalltestactionsaresetupandthetestcaseisreadytorun.ThisseparationofdesigntimeandruntimeofatestcaseleadstomisunderstandingsasaJavadeveloperisusedtoworkwithstatementsandmethodcallsthatperformimmediately.BasedonthatthemixtureofCitrusJavaDSLmethodcallsandnormalJavacodelogicinyourtestmayhaveleadtounexpectedbehavior.FollowingfromthatwedecidedtorefactortheJavaDSLmethodexecution.TheresultisanewTestRunnerconceptthatexecutesallJavaDSLmethodcallsimmediately.TheoldwayofbuildingthewholetestcasebeforeexecutionisrepresentedwithTestDesignerconcept.Sobothworldsarenowavailabletoyou.Seetestcasefordetails.
WebSocketsupport
TheWebSocketmessageprotocolbuildsontopofHttpstandardandbringsbidirectionalcommunicationtotheHttpclient-serverworld.WiththisreleaseCitrususersareabletosendandreceivemessageswithWebSocketconnections.TheHttpserverimplementationisnowabletodefinemultipleWebSocketendpoints.ThenewCitrusWebSocketclientisabletopublishmessagestotheserverviabidirectionalWebSocketprotocol.Seehttp-websocketfordetails.
JSONPathsupport
CitrusisabletoworkwithXpathexpressionsinseveralfieldswithinthetestingdomain(overwriteelements,ignoreelements,extractvaluesfrompayloads).NowthissupportofmanipulatingmessagepayloadsviaexpressionsisextendedwithJSONPath.SimilartoXpaththeJSONPathexpressionstatementsenableyoutofindelementsandvalues
CitrusReferenceGuide
543Changes2.3
![Page 544: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/544.jpg)
withinamessagepayload.NotverysurprisingtheJSONPathexpressionsworkwithJsonmessagepayloads.Withthenewreleaseyoucanoverwrite,ignoreandmanipulateJsonelementsusingJSONPathexpressions.Seejson-pathfordetails.
Customizemessagevalidators
TheframeworkoffersseveralmessagevalidatorimplementationsfordifferentmessageformatslikeXML,JSON,plaintextandsoon.InadditiontothatCitrushasasetofGroovyscriptmessagevalidators.AllthesevalidatorimplementationsareactivebydefaultsoyouareabletovalidateincomingmessagesaccordinglyinCitrus.Nowwiththisreleaseweaddedamorecomfortablewayofchangingtheframeworkvalidationfunctionality,particularwhenaddingnewcustomizedmessagevalidatorimplementations.Seevalidationfordetails.
Libraryupgrades
WehaveupgradedtheversionsofthemajordependencylibrariesofCitrus.ThisincludesTestNG,JUnit,SpringFramework,SpringWS,SpringIntegration,ApacheCamel,Arquillian,Jettyandmore.SoCitrusisnowworkingwithup-to-dateversionsofthewholemessagingandmiddlewareintegrationgang.
UpgradefromCitrus2.2
AlongwithnewfeaturesandimprovementswerefactoredandchangedsomepartsofCitrussoyoumighthavetosetthingsstraightwhenupgradingto2.3.Seethefollowinglistofthingsthatmightbebroughtuptoyou:
@CitrusTestannotation:Wehavemovedthe@CitrusTestannotationtoamorecommonpackage.Theoldpackagewascom.consol.citrus.dsl.annotations.CitrusTest.Thenewpackageiscom.consol.citrus.annotations.CitrusTest.SoyouhavetochangetheJavaimportstatementsinyourTestclasseswhenupgrading.
TestResult:WechangedtheTestResultinstantiationwhengeneratingthetestreports.TheTestResultclassnowworkswithstaticinstantiationmethodsforsuccess,skippedandfailedtests.Thisonlyaffectsyourcodewhenyouhavecreatedcustomtestreporters.
CitrusReferenceGuide
544Changes2.3
![Page 545: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/545.jpg)
CitrusTestBuilderdeprecation:AmajorrefactoringwasdoneintheTestBuilderJavaDSLcode.com.consol.citrus.dsl.TestBuilderandallitssubclassesweremarkedasdeprecatedandwilldisappearinnextversions.Soinsteadwenowsupportcom.consol.citrus.dsl.design.TestDesignerwhichbasicallyoffersthesamefunctionalityasformerTestBuilder.InadditionthatrefactoringbroughtanewwayofexecutingtheJavaDSLtestcases.Insteadofbuildingthewholetestcasebeforeexecutionisdoneasawholeyoucannowusethecom.consol.citrus.dsl.runner.TestRunnerimplementationinordertoexecuteeachtestactionintheJavaDSLimmediately.ThisisamoreJavalikewayofwritingCitrustestcasesasyoucanmixCitrustestactionexecutionwithnormalJavastatementsasusual.Readmoreaboutthenewapproachintestcase
Bugfixes
Bugsarepartofoursoftwaredevelopersworldandfixingthemispartofyourdailybusiness,too.FindingandsolvingissuesmakesCitrusbettereveryday.ForadetailedlistingofallbugfixespleaserefertothecompletechangeslogofeachreleaseinJIRA(http://www.citrusframework.org/changes-report.html).
CitrusReferenceGuide
545Changes2.3
![Page 546: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/546.jpg)
ChangesinCitrus2.2Citrus2.2isareleasemostlyaddingnewfeaturesaswellasimprovementstogivenCitrusfeatures.Bugfixesofcoursearealsopartofthepackage.Seethefollowingoverviewonwhathaschanged.
Arquilliansupport
ArquillianisawellknownintegrationtestframeworkthatcomeswithagreatfeaturesetwhenitcomestoJavaEEtestinginsideofafullqualifiedapplicationserver.WithArquiliianyoucandeployyourJavaEEservicesinarealapplicationserverofyourchoiceandexecutethetestsinsidetheapplicationserverboundaries.ThismakesitveryeasytotestyourJavaEEservicesinscopewithproperJNDIresourceallocationandotherresourcesprovidedbytheapplicationserver.CitrusisabletoconnectwiththeArquilliantestcase.SpeakinginmoredetailyourArquilliantestisabletouseaCitrusextensioninordertousetheCitrusfeaturesetinsidetheArquillianboundaries.Seearquillianfordetails.
JUnitsupport
CitrussupportsbothmajorplayersinunittestingTestNGandJUnit.UnfortunatelywedidnotofferthesamefeaturesupportforJUnitasitwasdoneforTestNG.NowwithCitrus2.2weimprovedtheJUnitsupportinCitrussoyouareabletouseallfeatureswithbothframeworks.Thisisespeciallyrelatedtousingthe@CitrusTestand@CitrusXmlTestmethodannotationsintestclasses.Seerun-junithowitworks.
Start/Stopserveraction
CitruswasmissingadedicatedtestactiontostartandstopCitrusservercomponentsattetruntime.Withthenewlyaddedtestactionsyouareabletostartandstopservercomponentsasyoulikewithinyourtestcase.Seeactions-manage-serverwithadetaileddescription.
CitrusAnttasks
CitrusReferenceGuide
546Changes2.2
![Page 547: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/547.jpg)
WediscontinuetosupporttheCitrusAnttasks.TheAnttaskswerenotverystableanlackedfullfeaturesupportwhenexecutingtestcaseswithJUnitinApacheAnt.InsteadweaddedabriefdescriptiononhowtoexecuteCitrustestswiththewelldocumentedandstabledefaultJUnitandTestNGanttasks.Seesetup-using-anthowitworks.
Bugfixes
Bugsarepartofoursoftwaredevelopersworldandfixingthemispartofyourdailybusiness,too.FindingandsolvingissuesmakesCitrusbettereveryday.ForadetailedlistingofallbugfixespleaserefertothecompletechangeslogofeachreleaseinJIRA(http://www.citrusframework.org/changes-report.html).
CitrusReferenceGuide
547Changes2.2
![Page 548: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/548.jpg)
ChangesinCitrus2.1Citrus2.1addssomeenhancementstotheCitrusfeaturesetaswellasbugfixesandimprovements.Seethefollowingoverviewonwhathaschanged.
SOAPMTOMsupport
SOAPMTOMstandsforMessageTransmissionOptimizationMechanismwhichallowsyoutosendandreceivelargeSOAPattachmentcontentsstreamedwithoptimizedresourceallocationonserverandclient.Manythankstocommunitycontributions(github/stonator)thatmadethishappenwithCitrusSOAPclientandserver.AsauseryoucanshoosetosendandreceiveSOAPattachmentswithMTOMoptimization.Seesoap-attachment-mtomfordetails.
SOAPenvelopehandling
InitsdefaultbehaviorCitruswillremovetheSOAPenvelopeforincomingSOAPrequestsjustprovidingtheSOAPbodyasmessagepayload.Thisismorestraightforwardinatestcasetoperformfurthervalidationsteps.HoweveritmightbemandatorytoseethewholeSOAPenvelopeinsidethetestcaseforspecialvalidation.AsauseryoucannowchoosehowtohandleincomingSOAPenvelopebydefinigthekeep-soap-envelopesettingontheCitrusSOAPservercomponents.Seesoap-keep-envelopefordetails.
SOAP1.2messagefactory
TheCitrusSOAPservercomponentwasmissingasettingfortheSOAPmessagefactorytouse.TheSOAPmessagefactoryimplementationdecideswhichSOAPversiontouse1.1or1.2.NowyoucansetthemessagefactoryontheservercomponentanddefinetheSOAPversiontouse.Seesoap-12fordetails.
TestNGdataproviderhandling
WeimprovedtheTestNGdataproviderhandlinginCitrus.NowyoucanusetheusualTestNGdataproviderannotationsinyourtestmethods.TestNGwillcalltheCitrustestcaseseveraltimeswithrespectiveparametersprovidedastestvariables.Thisreplaces
CitrusReferenceGuide
548Changes2.1
![Page 549: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/549.jpg)
theoldcitrusDataProvidermechanismthattriedtomakethingsworkinginakindofworkaround.Thenewproviderhandlingalsosupportsmultipledataprovidersinatestclass.run-testng-data-providersdescribeshowthisisworkingforyou.
Mailmessagenamespace
TheCitrusmailcomponentsenablemessageexchangeasmailclientandserver.ForvalidationpurposethecomponentsofferaXMLmailmessagerepresentation.Wehaveaddedatargetnamespacexmlns="http://www.citrusframework.org/schema/mail/message"andaXSDschemaforthisXMLmailmessagerepresentation.FromnowonyouhavetousethenamespaceaccordinglyinyourmailmessagepayloadswhensendingandreceivingmailmessagesinCitrus.SeemailhowtousethenewXMLmailmessagenamespace.
Sshmessagenamespace
WhensendingandreceivingmessagesviasshCitrusprovidesaXMLrepresentationforrequestandresponsedata.Thesesshmessagesfollowanewtargetnamespacexmlns="http://www.citrusframework.org/schema/ssh/message"andaXSDschema.ThismeansyouhavetousethenamespaceaccordinglyinyoursshmessagepayloadswhensendingandreceivingsshmessagesinCitrus.Seesshforfurtherdetails.
CitrusReferenceGuide
549Changes2.1
![Page 550: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/550.jpg)
ChangesinCitrus2.0Citrus2.0isamajorversionupgradeandthereforebigthingsshouldbehappening.InthefollowingsectionsweshortlydescribetheCitrusevolution.WewantyoutogetaquickoverviewofwhathashappenedandallthenewthingsinCitrus.Sohopefullyyoucanspotyourfavoritenewfeature.
Refactoring
InCitrus1.4webegantorefactortheconfigurationcomponentsinCitrus.ThisrefactoringwasfinalizedinCitrus2.0whichmeansthatalldeprecatedclassesandapiarenolongersupported.Theclasseswereremovedsoyougetcompilationerrorswhenusingthoseoldstuff.Ifyoustillusetheoldconfigurationseethishttp://citrusframework.org/migration-sheet.htmlinordertolearnhowtoupgradetothenewconfiguration.Itisworthtodoso!Inadditiontothatwedidrefactoringinfollowingfields:
ReplymessagecorrelationInsynchronouscommunicationscenariosCitrusoptionallycorrelatedmessagesacrosssendandreceivetestactions.Indefaultsettingthemessagecorrelationwasdisabled.With2.0releasewechangedthisbehaviortotheopposite.Nowmessagecorrelationisdonebydefaultwithadefaultcorrelationalgorithm.SoincaseyouusedtheDefaultReplyMessageCorrelatorinCitrusbeforeyouwillnothavetodosoinfutureasthisisdonebydefault.Themessagecorrelationgivesusmorerobusttestsespeciallywhenexecutingtestsinparallel.Inthetestcaseyoudonothavetodoanythingforpropermessagecorrelation.
CitrusmessageAPIWehaverefactoredtheCitrusmessageAPItousecustommessageobjectsinendpoints,consumersandproducers.Thishasnoaffectonyourtestsorconfigurationunlessyouhavewrittenendpointextensionsorcustomendpointsonyourown.Youmighthavetorefectoryourcodeaccordingly.HavealookattheCitrusendpointimplementationsinordertoseehowthenewmessageAPIworksforyou.
SleeptimeinmillisecondsThisissomethingthatwedefinitelycarryaroundsincethebeginningofCitrus.Thetimevaluesinsleeptestactionweredoneinseconds,whichisinconvenientwhenusingtimeperiodsbelowonesecondornonnatural
CitrusReferenceGuide
550Changes2.0
![Page 551: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/551.jpg)
numbers.Nowyoucanchoosetousemillisecondswhichismorelikelyhowyoushouldconfiguretimeperiodsanyway.Seeactions-sleepfordetails
AutosleeptimeinmillisecondsWeusedsecondswhenusingautosleepinrepeatonerrorcontainer.Thisledtothefactthatwewerenotabletosleeptimeperiodsbelowonesecond.Alsoitwasnotpossibletospecifynonnaturalnumberssuchas1.5secondsautosleeptime.Wechangedtomillisecondswhichismorelikelyhowyouareusedtoconfiguretimeperiodsanyway.Seecontainers-repeat-onerrorfordetails
Messagehandlervs.endpointadapterInpreviousreleasespriorto1.4wehadmessagehandlersonserversidethatwereabletoforwardincomingrequeststomessagechannelsorjmsdestinations.Theoldmessagehandlerimplementationswereremovedin2.0.Insteadyoushouldusetheendpoint-adapterimplementations.Seeendpoint-adapterhowthatworks.
XMLendpointreferenceattributeInaXMLtestcaseyoureferencethemessageendpointinthesendandreceiveactionswithaspecialattributecalledwith.Thisattributeisnolongersupportedandwasremoved.InsteadyoushouldusetheendpointattributewhichwasintroducedinCitrus1.4andhastheexactsamefunctionality.
Removedcitrus-adaptermoduleTheMavenmodulecitrus-adapterwasremoved.ClassesandAPImovedtocitrus-coremodule.ForendpointadaptersdousethenewconfigurationcomponentsthatwereintroducedinCitrus1.4.Seeendpoint-adapterfordetails.
WebServiceEndpointclassrenamedIntermsofpackagerefactoringthecom.consol.citrus.ws.WebServiceEndpointwasrenamedtocom.consol.citrus.ws.server.WebServiceEndpoint
Springframework4.x
IntermsofupgradingtheCitrusAPIdependenciesweintroducedSpring4.xversions.ThisincludesthecoreSpringframeworklibrariesaswellastheSpringIntegrationandSpringWebServiceprojectartifacts.SowiththemajorversionupgradelotsofAPIchangeswerealsodoneinCitruscodeinordertomeetthenewSpring4.xAPI.SowerecommendforyoutoalsouseSpring4.xversioninyourCitrusprojects.
FTPsupport
CitrusReferenceGuide
551Changes2.0
![Page 552: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/552.jpg)
NewmemberoftheCitrusfamilydealswithFTPconnectivity.Thenewcitrus-ftpmoduleprovidesaneatftpserverandclientimplementationsoyoucansendandreceivemessagesvieFTPmessagetransport.ftpdescribesthenewfunctionalityindetail.
Functionswithtestcontextaccess
Functionsarenowabletoaccessthetestcontext.Thisenablesyoutoaccessalltestvariablesandothercentraltestrelatedcomponentsinafunctionimplementation.ThereforethefunctionJavainterfacehasnowanadditionaltestcontextparameter.Refactoryourcustomwrittenfunctionsaccordinglytomeetthenewinterfacerules.Seehttp://www.citrusframework.org/tutorials-functions.htmlfordetails.
Validationmatcherwithtestcontextaccess
Justlikefunctionsnowvalidationmatchersareabletoaccessthetestcontext.Thisenablesyoutoaccessalltestvariablesandothercentraltestrelatedcomponentsinavalidationmatcherimplementation.ThevalidationmatcherJavainterfacehaschangedaccordinglywithanadditionaltestcontextparameter.Refactoryourcustomwrittenmatcherimplementationaccordinglytomeetthenewinterfacerules.
Messagelistenerwithtestcontextaccess
Messagelistenersdonowalsohaveaccesstothetestcontext.Thisismorepowerfulasyoucanaccesstestvariablesandothercentralcomponentswithinthetestcontext.
SOAPoverJMS
SOAPoverJMSwassupportedinCitrusfromtheverybeginning.UnfortunatelyyouhadtoalwaysspecifythewholeSOAPenvelopeinyourtestcase.SOAPenvelopehandlingisnowdoneautomaticallybyCitruswhenusingthenewSoapJmsMessageConverter.TheconvertertakescareonconstructingaproperSOAPenvelopemessage.Seejms-soapfordetails.
MultipleSOAPattachments
WhensendingandreceivingSOAPmessageswithCitrusasclientorserveryoucanaddonetomanyattachmentstothemessage.Beforeitwasonlypossibletohaveonesingleattachmentinamessage.NowyouhavenolimitsindefiningSOAPattachments.
CitrusReferenceGuide
552Changes2.0
![Page 553: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/553.jpg)
Seesoap-webservicesfordetails.
MultipleSOAPXMLheaderfragments
TheSOAPheadercanholdmultipleXMLheaderfragmentswithdifferentnamespacesandcontent.WithCitrus2.0youareabletoconstructsuchaSOAPmessagewithmultipleheadercontents.Seesoap-webservicesfordetails.
Createvariablevalidationmatcher
Anewvalidationmatcherimplementationisabletocreateanewvariableonthefly.Theactualfieldnameisusedasvariablenameandtheelementvalueasvariablevalue.Thevariablenamecanslobecustomizedwithoptionalvalidationmatcherparameter.ThisisagreatalternativetotheXPathexpressionevaluatingvariableextraction.AlsoveryhandsometousethisvalidationmatcherinJsonmessagepayloads.Seevalidation-matcher-variablefordetails.
Newconfigurationcomponents
AmajorpartoftheCitrusconfigurationisdoneinaSpringbeanapplicationcontext.CentralCitruscomponentsandfeaturesareaddedasSpringbeanstotheapplicationcontext.NowwithCitrus2.0wehaveaddedspecialconfigurationcomponentsforalmostallfeatures.ThismeansthatyoucaneasilyaddconfigurationusingthenewXMLschemacomponents.Seewhichcomponentsareavailable:
FunctionlibraryCustomfunctionlibrarieswithcustomfunctionimplementationsarenowconfiguredwiththefunction-libraryXMLschemacomponentsintheSpringapplicationcontextconfiguration.Seefunctionsfordetails.
ValidationmatcherlibraryCustomvalidationmatcherimplementationsarenowconfiguredwiththevalidation-matcher-libraryXMLschemacomponentsintheSpringapplicationcontextconfiguration.Seevalidation-matchersfordetails.
DatadictionaryDatadictionariesapplytoallmessagessendandreceivedintestcases.Youcandefinemultipledictionariesusingthedata-dictionaryXMLschemacomponentsintheSpringapplicationcontextconfiguration.Seedata-dictionaryfordetails.
CitrusReferenceGuide
553Changes2.0
![Page 554: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/554.jpg)
NamespacecontextConfigurationofaglobalnamespacecontextisnecessaryforXMLmessagepayloadsandXPathexpressionsusedinthetestcases.Thenamespace-contextXMLschemacomponentisusedintheSpringapplicationcontextconfigurationandsimplifiestheconfiguration.Seexpathfordetails.
Before/aftersuitecomponents
Whenexecutingtestactionsbeforetheactualtestrunyoucanusethesequencebeforesuitecomponents.WehaveimprovedthesecomponentstouseaspecialXMLschema.Thisenableseasyconfigurationofbothbeforeandaftersuiteactions.Inadditiontothatyoucanbindthesuiteactionstospecialpackages,testnamesorsuitenames.Soyoucannowhavemorethanonesequencebeforesuiteatthesametime.Accordingtotheenvironmentsettingsthebeforesuiteactionsareexecutedorleftout.Lastnotleastwehavedonethesameimprovementtothebeforetestactionsandwehaveintroducedaaftertestsequencecomponentforexecutionaftereachtest.Seehowthisisdoneintestsuite.
CitrusJMSmodule
JMSsupporthasbeenamajorpartofCitrusfromtheverybeginning.UptonowtheJMSfeatureswerelocatedincitrus-coreMavenmodule.WithCitrus2.0weintroducedaseparatecitrus-jmsMavenmodule.ThismeansthatyoumighthavetoaddproperMavendependencyofthisnewmoduleinyourexistingprojectwhenusingJMS.Seehowthisisdoneinjms.
CitrusReferenceGuide
554Changes2.0
![Page 555: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/555.jpg)
ChangesinCitrus1.4.x
Refactoring
ItwastimeforustodosomecoderefactoringinCitrus.ManyusersstruggledwiththeconfigurationoftheCitruscomponentsandprojectsetupwastooverboseinsomeareas.ThisiswhywetriedtoimprovethingswithworkingoverthebasicconceptsandcomponentsinCitrus.
TheoutcomeisanewCitrus1.4whichhasnewconfigurationcomponentsforsendingandreceivingmessages.AlsotheclientandservercomponentsforHTTPandSOAPhavechangedintermsofsimplification.Unfortunatelyrefactoringcomesalongwithcodedeprecation.Thisiswhyyouhavetoalsochangeyourprojectcodeandconfigurationinthefuture.ThisisespeciallywhenyouhavemadecodeadjustmentsandextensionstotheCitrusAPI.
ThegoodnewsnowisthatwithCitrus1.4botholdandnewconfigurationworksfine,soyoudonothavetochangeyourexistingprojectconfigurationwhencomingfromCitrus1.3.xandearlierversions.ButthereisalotofcodemarkedasdeprecatedinCitrus1.4.HavealookatwhathasbeenmarkedasdeprecatedandupdateyourcodetousethenewAPI.
WehavesetupamigrationsheetforuserscomingfromCitrus1.3.xandearlierversionsinordertofindaquickoverviewofwhathaschangedandhowtousethenewconfigurationcomponents:http://citrusframework.org/migration-sheet.html
Datadictionaries
Datadictionariesdefinedynamicplaceholdersformessagepayloadelementvaluesingeneralmanner.Intermsofsettingthesamemessageelementacrossalltestcasesandalltestactionsthedictionaryprovidesaneasykey-valueapproach.
WhendealingwithanykindofmessagepayloadCitruswillaskthedatadictionaryforpossibletranslationofthemessageelementscontained.ThedictionarykeysdomatchtoaspecificmessageelementdefinedbyXPathexpressionordocumentpathexpressionforinstance.TherespectivevalueisthensetonallmessagesinCitrus(inboundandoutbound).
CitrusReferenceGuide
555Changes1.4
![Page 556: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/556.jpg)
DictionariesdoapplytoXMLorJSONmessagedataandcanbedefinedinglobalorspecificscope.Findoutmoredetailedinformationaboutthistopicindata-dictionary
Mailadapter
Withthenewmailadapteryouareabletobothsendandreceivemailmessageswithinatestcase.ThenewCitrusmailclientproducesamailmimepartmessagewithusualmailheadersandatextbodypart.Optionalattachmentpartsaresupported,too.
OntheserversideCitrusprovidesaSMTPservertoacceptclientmailmessages.Theincomingmailmessagescanhavemultipletextpartsandattachmentparts.AsusualyoucanvalidatetheincomingmailmessagesregardingheadersandpayloadwiththewellknownvalidationcapabilitiesinCitrus.
Readmoreaboutthenewmailmoduleinmail
Endpointadapter
EndpointadaptershelptocustomizethebehaviorofaCitrusserversuchasHTTPorSOAPwebservers.Theendpointadapterisresponsibleofcreatinganendpointthatrespondstoinboundrequests.YoucancustomizethebehaviorsotheCitrusserverhandlesincomingrequestsasyoulike.
BydefaulttheCitrusserverusesachannelendpointadaptersoincomingmessagesgetforwardedtoaninmemorymessagechannel.Thereareseveralotherimplementationsavailableasendpointadapter.Readmoreaboutthatinendpoint-adapter
Globalvariablescomponent
WeaddedaglobalvariablesXMLconfigurationcomponentformorecomfortableusageinbasicSpringapplicationcontextconfiguration.ThecomponentisabletocreatenewglobalvariablesthatarevalidacrossallCitrustestcases.Thiscanalsobedonebyloadingapropertyfilefromanexternalfileresource.Findouthowtousitintestcase-global-variables
Jsontextvalidatormode
TheJsontextvalidatorisnowabletooperateintwodifferentmodes.Thestrictmodeisthedefaultmodeandvalidationincludesalsoastrictcheckonallsub-objectsandJSONarrayelements.Soifthereisanobjectmissingthevalidationwillfailimmediately.
CitrusReferenceGuide
556Changes1.4
![Page 557: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/557.jpg)
SometimesitmaybeaccuratetoonlyvalidateasubsetofallJSONobjectsinthedatastructure.Thereforethenon-strictmodedoesnotcheckonobjectattributecounts.Seemoredescriptioninvalidation-json
HTTPRESTspecificJavaDSLoptions
WhensendingandreceivingHTTPmessagesonRESTAPIsyoucannowuseinterfacespecificoptionsintheJavaDSL.Thisreferstorequesturi,contextpath,queryparametersandHTTPstatuscodesforinstance.WiththisenhancementyouarenowmorecomfortableinhandlingRESTAPIcallsinCitrus.Findouthowtousitinhttp
SOAPHTTPvalidation
WhilereceivingSOAPmessagesoverHTTPwearenowabletoalsoverifytheusedHTTPuri,context-pathandqueryparameters.YoucanexpectclientstousethosevaluesinyourreceiveactionasyouwoulddoinnormalHTTPcommunicationwithinCitrus.ThiscompletestheHTTPservervalidationwhenusingSOAPoverHTTP.Readmoreaboutitinsoap-webservices
ApacheCamelintegration
ApacheCamelisagreatenterpriseintegrationplatformthatimplementstheenterpriseintegrationpatternsforbuildingpowerfulmediationandroutingrulesformessagebasedintegrationapplications.WiththenewsupportforcamelendpointsinCitrusyoucaninteractwithApacheCamelcomponentsforsendingandreceivingmessages.ApacheCameloffersafinesupportfordifferentmessagetransportsthatnowcanbeusedinCitrusalso.InadditiontothatyoucanputyourCamelapplicationtothetestwithloadingoftheApacheCamelcontextwithallyourroutedefinitions.Citrusisabletointeractwiththeseroutesinasynchronousandsynchronouscommunicationscenarios.Readaboutitincamel.
Vert.xintegration
Vert.xisaverypowerfulapplicationplatformthatprovidesscalablemessagingforseveralmessagetransportssuchasHTTP,WebSockets,TCPandmore.Vert.xalsohasadistributedeventbusthatconnectsmultipleVert.xinstancesacrossthenetwork.WithCitrus1.4theVert.xplatformisintegratedwithCitruseventbusendpoints.Soyou
CitrusReferenceGuide
557Changes1.4
![Page 558: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/558.jpg)
canparticipateincommunicatingtotheVert.xeventbusfromCitrustestcase.ThisenablesyoutoaddautomatedintegrationteststotheVert.xplatform.Readaboutthatinvertx.
Dynamicendpointcomponents
EndpointsrepresentthebasecomponentinCitrusforsendingandreceivingmessages.TheendpointusuallyisdefinedinsidetheCitrusSpringapplicationcontextasSpringbeancomponent.Nowitisalsopossibletocreatedynamicendpointdefinitionsattestruntime.ThiscomesinveryhandywhenyoujustwanttosendorreceiveamessagewithCitrusasis.Youdonotneedtoaddthecompleteendpointconfigurationbutonlyuseaspecialendpointuripattern.Citruswillcreatetheendpointatruntimeautomatically.Learnhowtousethedynamicendpointpatterninendpoint-components.
CitrusReferenceGuide
558Changes1.4
![Page 559: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/559.jpg)
ChangesinCitrus1.3.x
@CitrusTestand@CitrusXmlTestannotations
WiththenewJavaDSLcapabilitiesCitruscreatednewwaysofexecutingtestcaseswithinaTestNGorJUnittestclass.Nowweevenimprovedtheusageherewithtwonewannotations@CitrusTestandCitrusXmlTest.Theintegrationintotheunittestclasshasneverbeeneasierforyou.
ThenewCitrusannotationsgodirectlytoyourunittestmethods.WiththisenhancementyoucanhavemultipleCitrustestcasesinonesingleJavaclassandtheCitrustestsnowareabletocoexistwithotherunittestmethods.YoucanevenmixJavaDSLandXMLCitrustestcasesinasingleJavaclass.
TheXMLCitrustestscanbegroupedtoasingleJavaclasswithmultipleXMLfilesloadedduringexecution.ThereisevenapackagescanforallCitrusXMLfileswithinadirectorystructuresoyoudonothavetocreateaJavaclassforeachtestcaseanymore.
Wehavechangedthedocumentationinthisguidesoyoucanseehowtousethenewannotations.Fordetailedoverviewseerun-config-testng.AlsoseeourCitrusblogwherewecontinuouslydescribethemanypossibilitiesthatyouhavewiththenewannotations.
@CitrusParametersannotation
CitrusisabletousethefabulousTestNGdataprovidercapabilitiesinordertoexecuteatestcaseseveraltimeswithdifferentdataprovidedformexternalresources.Thenew@CitrusParametersannotationhelpstosetparameternameswhichareusedastestvariablenamesinthetestcase.
Schemarepositoryconfigurationcomponents
Definingschemarepositoriesandschemas(xsd,wsdl)iscommonuseinCitrus.WehaveaddedXMLbeandefinitionparserssodefiningthosecomponentsislessverbose.YoucanusetheCitruscitrus:schema-repositoryandcitrus:schemacomponentsinyourSpringapplicationcontextconfiguration.Thecomponentsdoreceiveseveralattributesforfurtherconfiguration.XSD,WSDLandschemacollectionsaresupportedhere.
CitrusReferenceGuide
559Changes1.3
![Page 560: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/560.jpg)
Checkoutxsd-validationforexampleshowtousethenewconfigurationcomponents.
Changedatefunction
WehaveaddedanewCitrusfunctioncitrus:changeDate()thatisavailableforyoubydefault.Thefunctionchangesagivendatevalueaddingorremovingadatetimeoffset(e.g.year,month,day,hour,minute,second).Soyoucanmanipulateeachdatevaluealsothoseofdynamicnaturecomingwithsomemessage.
Seefunctions-changedateforexamplesanddetailedsyntaxusageofthisfunction.
Weekdayvalidationmatcher
Thenewweekdayvalidationmatcheralsoworksondatevalues.Thematcherchecksthatagivendatevalueevaluatestoaexpecteddayoftheweek.Sotheusercancheckthatadatefieldisalwaysasaturdayforinstance.Thisisveryhelpfulwhencheckingthatagivendatevalueisnotaworkingdayforexample.
Seevalidation-matcher-weekdayforsomemoredetaileddescriptionofthematcher'scapabilities.
JavaDSL
Citrususers,inparticularthosewithdevelopmentexperience,dooftentellmeaboutthenastyXMLcodetheyhavetodealwithforwritingCitrustestdefinitions.DeveloperswanttowriteJavacoderatherthanXML.AlthoughIpersonallydoliketheCitrusXMLtestsyntaxwehaveintroducedaJavaDSLlanguageforwritingCitrustestswithJavaonly.
WehaveintroducedtheJavaDSLtoallmajortestactionfeaturesinCitrussoyoucanswitchwithouthavingtoworryaboutloosingfunctionality.DetailscanbeseeninthetestactionsectionwhereweaddedJavaDSLexamplesalmosteverywhere(actions).ThebasicJavaDSLsetupisdescribedintestcase.
XHTMLmessagevalidation
MessagevalidationforHtmlcodewasnotreallycomfortableasHtmldoesnotconfirmtobewellformedandvalidXMLsyntax.XHTMLtriestoclosethisgapbyautomaticallyresolvingallHtmlspecificXMLsyntaxruleviolations.WithCitrus1.3weintroducedaXHTMLmessagevalidatorwhichdoesthemagicforconvertingHtmlcodetoproper
CitrusReferenceGuide
560Changes1.3
![Page 561: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/561.jpg)
wellformedandvalidXML.InatestcaseyoucanthenusethefullXMLvalidationpowerinCitrusinordertovalidateincomingHtmlmessages.Sectionvalidation-xhtmldealswiththenewvalidationcapabilitiesforHtml.
MultipleSOAPfaultdetailsupport
SOAPfaultmessagescanholdmanySOAPfaultdetailelements.CitruswasabletohandleasingleSOAPfaultdetailonsendingandreceivingtestactionsfromtheverybeginningbutmultipleSOAPfaultdetailelementswerenotsupported.FortunatelythingsaregettingbetterandyoucansendandreceiveasmanyfaultdetailelementsasyoulikeinCitrus1.3.ForeachSOAPfaultdetailyoucanspecifyindividualvalidationrulesandexpectations.Seesoap-faultsfordetaileddescription.
Jettyserversecurityhandler
WithourJettyservercomponentyoucansetupHttpmockserversveryeasy.TheserverisautomaticallyconfiguredtoacceptHttpclientconnectionsandtoloadaSpringapplicationcontextonstartup.Nowyoucanalsosetsomemoredetailsonthisautomaticserverconfiguration(e.g.servercontextpath,servletnamesorservletmappings).Inadditiontothatyoucanaccessthesecuritycontextofthewebcontainer.Thisenablesyoutosetupsecurityconstraintssuchasbasicauthenticationonserverresources.Clientsarethenforcedtoauthenticateproperlywhenaccessingtheserver.Unauthorizeduserswillget401accessdeniederrorsimmediately.Seehttp-basic-auth-serverfordetails.OfcoursethisalsoappliestoourSOAPWebServiceJettyservercomponents(soap-basic-auth-server).
Testactors
Weintroducedanewconceptoftestactorsforsendingandreceivingtestactions.Thisenablesyoutolinkatestactor(e.g.interfacepartnerapplication,backendapplication)toatestactioninyourtest.Followingfromthatyoucanenable/disabletestactorsandalllinkedtestactionsveryeasy.ThisenablesustoreuseCitrustestcasesinend-to-endtestscenarioswherenotallinterfacepartnersgetsimulatedbyCitrus.Ifyouliketoreadmoreaboutthisconceptfollowthedetailedinstructionintest-actors.
SimulateHttperrorcodeswithSOAP
CitrusReferenceGuide
561Changes1.3
![Page 562: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/562.jpg)
CitrusprovidesSOAPWebServicesserversimulationwithclientsconnectingtotheserversendingSOAPrequests.AsaserverCitrusisnowabletosimulateHttperrorcodeslike404Notfoundand500Internalservererror.BeforethattheCitrusSOAPserverhadtoalwaysrespondwithaproperSOAPresponseorSOAPfault.Seesoap-http-errorsfordetails.
SSHserverandclient
TheCitrusfamilyhasraisedanewmemberinaddingSSHconnectivity.WiththenewSSHmoduleyouareabletoprovideafullstackSSHserver.TheSSHserveracceptsclientconnectionsandyouasatestercansimulateanySSHserverfunctionalitywithpropervalidationasitisknowntoCitrusSOAPandHTTPmodules.InadditiontothatyoucanalsousetheCitrusSSHclientinordertoconnecttoanexternalSSHserver.YoucanexecuteSSHcommandsontheSSHserverandvalidatetherespectiveresponsedata.Thefulldescriptionisprovidedinssh.
ANTruntestaction
WiththisnewtestactionyoucancallANTbuildsfromyourtestcase.TheactionexecutesoneormoreANTbuildtargetsonabuild.xmlfile.YoucanspecifybuildpropertiesthatgetpassedtotheANTbuildandyoucanaddacustombuildlistener.IncasetheANTbuildrunfailsthetestfailsaccordinglywiththebuildexception.Seeactions-antrunfordetails.
Pollingintervalforreplyhandlers
WithsynchronouscommunicationinCitruswealwayshaveacombinationofasynchronousmessagesenderandareplyhandlercomponent.Thesetwoperformahandshakewhenpassingsynchronousreplymessagestothetestforfurtherprocessingsuchasmessagevalidation.Whilethesenderiswaitingforthesynchronousresponsetoarrivethereplyhandlerpollsforthereplymessage.Thispollingforreplymessageswasdoneinastaticwaywhichoftenledtotimedelaysaccordingtolongpollingintervals.NowwithCitrus1.3youcansetthepolling-intervalforthereplyhandlerasyoulike.ThissettingisvalidforallreplyhandlercomponentsinCitrus(citrus-jms,citrus-http,citrus-ws,citrus-channel,citrus-shh,andsoon).
Upgradingfromversion1.2
CitrusReferenceGuide
562Changes1.3
![Page 563: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/563.jpg)
IfyouarecomingfromCitrus1.2youmayhavetolookatthefollowingpointsinordertohaveasmoothupgradetothenewreleaseversion.
JettyversionupgradeWeareusingJettyalotforstartingHttpservermockswithinCitrus.InordertostayuptodateweupgradedtoJetty8.1.7versionwiththisCitrusrelease.ThisimpliesthatpackagenamesdidchangeforJettyAPI.IngeneralthereisnoconflictforyouasaCitrususer,butyoumaywanttoadjustyourloggingconfigurationaccordingtonewJettypackages.Jettypackagenamesdidchangefromord.mortbaytoorg.eclipse.jetty.
SpringversionupgradeStayinguptodatewiththeversionsof3rdlibrarydependenciesisquiteimportantforus.Soweupgradeourdependenciestonewerversionswitheachrelease.Aswedidonlyupgrademinorversionsthereisnosignificantchangeorproblemstobeexpected.HoweveryoumaytakecareonversionsandreleasechangesintheSpringworldfordetailsandmigration.
TIBCOmoduleWedecidedtoputtheTIBCOmoduleseparatelyasitisaveryspecialconnectivityadapterforTIBCOsoftwareonly.SoyouwillnotfindtheTIBCOmodulewithintheCitrusdistributionanymore.WewillmaintainaTIBCOconnectivityadapterseparatelyinthefuture.
CitrusReferenceGuide
563Changes1.3
![Page 564: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/564.jpg)
ChangesinCitrus1.2
Springversionupdate
WehavesomemajorversionupgradesinourSpringdependencies.WearenowusingSpring3.1.1,SpringIntegration2.1.2andSpringWS2.1.0.Thisupgradewasoverdueforsometimeandisdefinitelyworthit.WiththeseupgradeswehadtoapplysomechangesinourAPI,too.ThisisbecauseweareusingtheSpringclassesalotinourcode.Seetheupgradeguideinthischapterforallsignificantchangesthatmightaffectyourproject.
Newgroovyfeatures
CitrusextendedthepossibilitiestoworkwithscriptlanguageslikeGroovy.YoucanuseGroovy'sMarkupBuildertocreateXMLmessagepayloads.YourGroovycodegoesrightintothetestcaseorcomesfromexternalfile.WithMarkupBuilderyoudonotneedtocareaboutXMLmessagesyntaxandoverhead.Justfocusonthepuremessagecontent.Youcanreadthedetailsingroovy-markupbuilder.
FurtherGroovyfeaturegoestothevalidationcapabilities.InsteadofworkingwithXMLDOMtreecomparisonandXPathexpressionvalidationyoucanuseGroovyXMLSlurper.ThisisveryusefulforthoseofyouwhoneedtodocomplexmessagevalidationanddonotliketheXML/XPathsyntaxatall.WithXMLSlurperyoucanaccesstheXMLDOMtreevianamedclosureoperationswhichfeelsgreat.ThisespeciallycomesinhandyforcomplexgenericXMLstructuresasyoucansearchforelements,sortelementlistandusethepowerfulcontainsoperation.Thisisalldescribedingroovy-xmlslurper.
SomeotherGroovysupportextensioncomesinSQLresultsetvalidation(actions-database-groovy).WhenreadingdatafromthedatabasesomeoneisabletovalidationtheresultingdatarowsetwithGroovyscript.ThescriptcodeeasilyaccessestherowsandcolumnswithGroovy'sout-of-the-boxlistandmaphandling.Thisaddsverypowerfulvalidationtomulti-rowdatasetsfromthedatabase.
SQLmulti-lineresultsetvalidation
CitrusReferenceGuide
564Changes1.2
![Page 565: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/565.jpg)
InthisnewCitrusversionthetestercanvalidateSQLQueryresultsthathavemultiplerows.InthepastCitruscouldonlyhandleasinglerowintheresultset.Nowthisnewreleasebringslightintothedark.SeealsothenewGroovySQLresultsetvalidationwhichfitsbrilliantforcomplexmulti-rowSQLresultsetvalidation.Thedetailscanbefoundinactions-database-query
Extendedmessageformatsupport
InpreviousversionsCitruswasprimarydesignedtohandleXMLmessagepayloads.WiththisnewreleaseCitrusisalsoabletoworkwithothermessageformatssuchasJSON,CSV,PLAINTEXT.Thisappliestosendingmessagesaswellasreceivingandparticularlyvalidatingmessagepayloads.ThetestercanspecifyseveralmessagevalidatorsinCitrusfordifferentmessageformats.Accordingtotheexpectedmessageformatthepropervalidatorischosentoperformthemessagevalidation.
WehaveimplementedaJSONmessagevalidatorcapableofignoringspecificJSONentriesandhandlingJSONArrays.Wealsoprovideaplaintextmessagevalidatorwhichisverybasictobehonest.Theframeworkisreadytoreceivenewvalidatorimplementationssoyoucanaddcustomvalidatorsforyourspecificneeds.
NewXMLfeatures
XMLnamespacehandlingistediousexpeciallyifyouhavetodealwithalotofXPathexpressionsinyourtests.BeforeyouhadneedtospecifyanamespacecontextfortheXPathexpressioneverytimeyouusetheminyourtest-nowyoucanhaveacentralnamespacecontextwhichdeclaresnamespacesyouuseinyourproject.Thesenamespacesidentifiedbysomeprefixareavailablethroughoutthetestprojectwhichismuchmoremaintainableandeasytouse.Seehowitworksinxpath-namespace.
SOAPsupportimprovements
WsAddressingstandardisnowsupportedinCitrus(soap-ws-adressing).ThismeansyoucandeclarethespecificWsAddressingmessageheadersonmessagesenderlevelinordertosendmessageswithWsAddressingfeature.TheheaderisconstructedautomaticallyforallSOAPmessagesthataresentoverthemessagesender.
DynamicSOAPendpointuriresolverenablesyoutodynamicallyaddressSOAPendpointsduringatest.SometimesamessagesendermaydynamicallyhavetochangetheSOAPurlforeachcall(e.g.addressdifferentrequesturiparts).Withaendpointuri
CitrusReferenceGuide
565Changes1.2
![Page 566: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/566.jpg)
resolversetonthemessagesenderyoucanhandlethisrequirementveryeasy.Thetipfordynamicendpointresolvingwasaddedtosoap-sender
WealsosimplifiedthesynchronousSOAPHTTPcommunicationwithintestcases.InpreviousversionsyouhadtobuildcomplexparallelandsequentialcontainerconstructsinordertocontinuewithtestexecutionwhiletheSOAPmessagesenderiswaitingforthesynchronousresponsetoarrive.NowyoucansimplyforkthemessagesendingactionandcontinuewithfurthertestactionswhilesynchronousSOAPcommunicationtakesplace.Seethesoap-fork-modefordetails
SomereallysmallchangeintroducedwiththisreleaseisthefactthatCitrusnowlogsSOAPmessagesintheirpurenature.ThismeansthatyoucanseethecompleteSOAPenvelopeofmessagesintheCitruslogfiles.Thisismorethanhelpfulwhensearchingforerrorsinsideyourtestcase.
HttpandRESTfulWebServices
WehavechangedHttpcommunicationcomponentsforfullsupportofRESTfulWebServicesonclientandserverside.TheHttpclientnowusesSpring'sRESTsupportforHttprequests(GET,PUT,DELETE,POST,etc.).Theserversidehaschanged,too.TheHttpservernowprovidesRESTfulWebServicesandiscomplianttotheexistingSOAPJettyserverimplementationinCitrus.IfyouwanttoupgradeexistingprojectstothisversionyoumayhavetoadjusttheSpringapplicationcontextconfigurationtosomeextent.
Fordetailshavealookattheupgradeguide(history-upgrading)inthischapterorfinddetailedexplanationstothenewHttpcomponentsinhttp.
HTMLreporting
CitrusprovidesHTMLreportsaftereachtestrunwithdetailedinformationonthefailedtests.Youcanimmediatelyseewhichtestsfailedinexecutionandwheretheteststopped.reporting-htmlprovidesdetailsonthisnewfeature.
Validationmatchers
Thenewvalidationmatcherswillputthemessagevalidationmechanismstoanewlevel.Withvalidationmatchersyouareabletoexecutepowerfulassertionsoneachmessagecontentelement.ForinstanceyoucanusetheisNumbervalidationmatcherforchecking
CitrusReferenceGuide
566Changes1.2
![Page 567: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/567.jpg)
thatamessagevalueisofnumericnature.Weaddedseveralmatcherimplementationsthatarereadyforusageinyourtestbutyoucanalsowriteyourcustomvalidationmatchers.Havealookatvalidation-matchersfordetails.
Conditionalcontainer
Thenewconditionaltestactioncontainerenablesyoutoexecutetestactionsonlyincaseabooleanexpressionevaluatestotrue.Sothenestedtestactionsinsidethecontainermaybenotexecutedatallincaseaconditionisnotmet.Seecontainers-conditionalfordetails.
Supportformessageselectorsonmessagechannels
SpringIntegrationmessagechannelsdonotsupportmessageselectorslikeJMSqueuesdoforexample.WithCitrus1.2weimplementedasolutionforthisissuewithaspecialmessagechannelimplementation.Soyoucanusethemessageselectorfeaturealsowhenusingmessagechannels.Gotomessage-channel-selector-supportfordetails.
Newtestactions
Weintroducedsomecompletelynewtestactionsinthisreleaseforyou.Thenewactionsarelistedbelow:
Purgemessagechannelaction()
Seeactionsfordetailedinstructionshowtousethenewactions.
Newfunctions
WeintroducedsomenewdefaultCitrusfunctionsthatwilleasethetesterslife.Thisincludescommonlyusedfunctionslikeencoding/decodingbase64bindarydata,escapingXMLandgeneratingrandomJavaUUIDvalues.Thesearethenewfunctionsinthisrelease:
citrus:randomUUID()citrus:cdataSection()citrus:encodeBase64()citrus:decodeBase64()citrus:digestAuthHeader()citrus:localHostAddress()
CitrusReferenceGuide
567Changes1.2
![Page 568: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/568.jpg)
Seefunctionsfordetaildescriptionsofeachfunction.
Upgradingfromversion1.1
IfyouarecomingfromCitrus1.1finalyoumayhavetolookatthefollowingpoints.
SpringversionupdateWedidsomemajorversionupgradesonourSpringdependencies.WearenowusingSpring3.1.1,SpringIntegration2.1.2andSpringWS2.1.0.ThesenewmajorreleasesbringsomecodechangesinourCitrusAPIwhichmightaffectyourcodeandconfiguration,too.Sopleaseupdateyourconfiguration,itisdefinitelyworthit!
SpringIntegrationheaders:With2.0.xversionSpringIntegrationhasremovedtheinternalheaderprefix("springintegration_").Soinsomecasesyoumightusethoseinternalheadernamesinyourtestcasesinordertosynchronizesynchronouscommunicationwithinternalmessageids.YourtestcasewillfailaslongasyouusetheoldSpringinternalheaderprefixinthetest.Simplyremovetheheaderprefixwhereverusedandyourtestisupandrunningagain.
Messagevalidator:YouneedtospecifyatleastonemessagevalidatorintheSpringapplicationcontext.BeforethiswasinternallyastaticXMLmessagevalidator,butnowweofferdifferentvalidatorsforseveralmessageformatslikeXMLandJSON.PleaseseetheJavaAPIdoconMessageValidatorinterfaceforavailableimplementations.IfyoujustliketokeepitasitwasbeforeaddthisbeantotheSpringapplicationcontext:
<beanid="xmlMessageValidator"class="com.consol.citrus.validation.xml.DomXmlMessageValidator"
Testsuite:Wehaveeliminated/changedtheCitrustestsuitelogicbecauseitduplicatesthosetestsuitesdefinedinTestNGorJUnit.InolderversionsthetesterhadtodefineaCitrustestsuiteinSpringapplicationcontextinordertoexecutetestactionsbefore/afterthetestrun.Nowthesetasksbeforeandafterthetestrunaredecoupledfromatestsuite.YoudefinetestsuitesexclusivelyinTestNGorJUnit.Thetestactionsbefore/afterthetestrunareseparatelydefinedinSpringapplicationcontextsoyouhavetochangethisconfigurationinyourCitrusproject.
Seetestsuitefordetailsonthisconfigurationchanges.
JUnitvs.TestNG:WesupportbothfamousunittestingframeworksJUnitandTestNG.Withthisreleaseyouarefreetochooseyourpreferedone.Inthismanner
CitrusReferenceGuide
568Changes1.2
![Page 569: Table of Contents - Citrus Frameworkcitrusframework.org/citrus/reference/2.7.1/pdf/citrus... · 2019-01-28 · Java 8 Citrus is now using Java 8. This is mainly because we need to](https://reader034.fdocuments.in/reader034/viewer/2022042221/5ec746ec6c6fa53e421f4eb8/html5/thumbnails/569.jpg)
youneedtoaddeitheraJUnitdependencyoraTestNGdependencytoyourprojectonyourown.WedonothavestaticdependenciesinourMavenPOMtoneitherofthosetwo.OnoursidethesedependenciesaredeclaredoptionalsoyoufeelfreetoaddtheoneyoulikebesttoyourMavenPOM.JustaddaJUnitorTestNGdependencytoyourMavenprojectoraddtherespectivejarfiletoyourprojectifyouuseANTinstead.
CitrusReferenceGuide
569Changes1.2