43
Eective out-of-container Integration Testing Sam Brannen Swi+mind GmbH

Effective out-of-container Integration Testing

Embed Size (px)

DESCRIPTION

Modern application frameworks like Spring promote a POJO-based programming model, and POJOs are inherently easy to unit test. But how can we effectively integration test our application outside the container while still getting as close to a production-like environment as possible? This session will show attendees how to approximate a target production environment using the Spring TestContext Framework to drive fast, repeatable, "out-of-container" integration tests. To simulate a live system, the session will cover open source integration testing techniques such as the use of in-memory databases, JMS providers, and Servlet containers as well as mock SMTP and FTP servers.

Citation preview

Page 1: Effective out-of-container Integration Testing

Effective out-of-container Integration Testing

SamBrannenSwi+mindGmbH

Page 2: Effective out-of-container Integration Testing

SpeakerProfile

•  SeniorSo+wareConsultant–Swi+mindGmbH•  Javadeveloperwith13+years'experience•  SpringFrameworkCoreDeveloper– AuthoroftheSpringTestContextFramework

•  PreviousSpringSourcedmServer™developer•  RegularspeakeratconferencesonSpring,dmServer,Java,OSGi,andtesOng

•  LeadauthorofSpringinaNutshell;chieftechnicalreviewerforSpringRecipes

Page 3: Effective out-of-container Integration Testing

Agenda

•  Background•  GoalsofIntegraOonTesOng•  TheChallenge•  ProposedSoluOon•  DIandIoCasEnablers•  SimulaOngaProducOonEnvironment•  SpringTestContextFramework•  Q&A

Page 4: Effective out-of-container Integration Testing

Background

Page 5: Effective out-of-container Integration Testing

TypesofTests

•  unittests•  integraOontests–  componentinteracOon:mulOpleunits

–  cross‐processinteracOon:database,mail,etc.

•  systemtests– end‐to‐endtesOngwithlivesystems

•  useracceptancetests

Page 6: Effective out-of-container Integration Testing

UnitTests

•  aresimpletosetup•  usedynamicmocksorstubsfordependencies

•  instanOatetheSUTandtestit•  runfast•  butonlytestasingleunit

Page 7: Effective out-of-container Integration Testing

IntegraOonTests

•  testinteracOonsbetweenmulOplecomponents

•  relaOvelyeasytosetupwithoutexternalsystemdependencies

•  challengingtosetupwithexternalsystemdependencies

•  morechallengingwhen/ifapplicaOoncodedependsonthecontainer

Page 8: Effective out-of-container Integration Testing

ModernEnterpriseJavaApplicaOons

•  Integratewithexternalsystems– SMTP,FTP,LDAP,RDBMS,WebServices,JMS

•  Relyoncontainer‐providedfuncOonality– datasources,connecOonfactories,transacOonmanager

Page 9: Effective out-of-container Integration Testing

GoalsofIntegra3onTes3ng

Page 10: Effective out-of-container Integration Testing

EffecOveIntegraOonTesOng

•  Fast•  Repeatable•  Automated

•  Easytoconfigure•  Providegoodcodecoverageofend‐to‐endbusinessusecases

Page 11: Effective out-of-container Integration Testing

Out‐of‐container

•  Zerorelianceonavailabilityofexternalsystems

•  Canberunanywhere– developerworkstaOon– CIserver

•  ApproximateatargetproducOonenvironment

Page 12: Effective out-of-container Integration Testing

TheChallenge

Page 13: Effective out-of-container Integration Testing

Howcanweeffec9velyintegraOontestanenterpriseJavaapplicaOon...

outsidethecontainer...

whilesOllge_ngascloseaspossibletoaproducOon‐likeenvironment?

Page 14: Effective out-of-container Integration Testing

ProposedSolu3on

Page 15: Effective out-of-container Integration Testing

ApproximatetheproducOonenvironmentby...

•  Usingopensourcelibrariesandframeworkstosimulate– asingleexternalsystemdependency,or– mulOpleexternalsystemdependencies

•  UsingtheSpringTestContextFrameworktodrivefast,out‐of‐containerintegraOontests– withsimulatedexternalsystemsstartedin‐memory

Page 16: Effective out-of-container Integration Testing

DIandIoCasEnablers

DependencyInjec9onandInversionofControlcollec9velydecoupleapplica9oncodefromthedeploymentenvironment.

Page 17: Effective out-of-container Integration Testing

DIandIoCIncreaseTestability

•  Dependenciesareinjected,notexplicitlyinstanOated– NotonlyforapplicaOoncomponents,butalsoforinfrastructurecomponents

•  JNDIlook‐upsforcontainerprovidedresources– EJBs,datasources,connecOonfactories,etc.

•  Programmingtointerfaces– AllowsustotransparentlyswapimplementaOons

Page 18: Effective out-of-container Integration Testing

Simula3ngaProduc3onEnvironment

Page 19: Effective out-of-container Integration Testing

Step1

•  EnsureyourapplicaOonconfiguraOoncanbesplitinto:– applicaOon‐specificconfiguraOon•  businesslogic•  servicelayer,repositorylayer,etc.

– environment‐specificconfiguraOon•  infrastructure

Page 20: Effective out-of-container Integration Testing

Step2

•  Ensureenvironment‐specificcomponentscanbeeasilyoverriddenintestconfiguraOon–forexample,byusingwelldefinedbeanIDs.– DataSource:dataSource– PladormTransacOonManager:transac9onManager

–  JMSConnecOonFactory:connec9onFactory

Page 21: Effective out-of-container Integration Testing

Step3

•  Useopensourcereplacementsforenvironment‐specificcomponents– preferablyconfigurableviaSpringApplicaOonContext

–  typicallyin‐memory(a.k.a.,embeddedmode)

Page 22: Effective out-of-container Integration Testing

OpenSourceFrameworksforEmbeddedUse

Page 23: Effective out-of-container Integration Testing

Database

•  Useanin‐memorydatabasesuchas– HSQL,H2,orDerby

•  Spring3.0providesexplicitsupportfor– Embeddeddatabases– PopulaOngexisOngdatabases

Page 24: Effective out-of-container Integration Testing

EmbeddedDatabaseinXML<jdbc:embedded-database id="dataSource" type="H2"> <jdbc:script location="classpath:/my-schema.sql" /> <jdbc:script location="classpath:/my-data.sql" /></jdbc:embedded-database>

Or simply…

<jdbc:embedded-database id="dataSource" />

Page 25: Effective out-of-container Integration Testing

EmbeddedDatabaseinCodeprivate EmbeddedDatabase db;

@Before public void launchDatabase() { db = new EmbeddedDatabaseBuilder() .addDefaultScripts() .build();}// tests …

@After public void shutdownDatabase() { db.shutdown();}

Page 26: Effective out-of-container Integration Testing

PopulateDatabaseinXML<jdbc:initialize-database data-source="dataSource"> <jdbc:script location="classpath:/schema_01.sql" /> <jdbc:script location="classpath:/schema_02.sql" /> <jdbc:script location="classpath:/data_01.sql" /> <jdbc:script location="classpath:/data_02.sql" /></jdbc:initialize-database>

Page 27: Effective out-of-container Integration Testing

JMS

•  Useanin‐memorymessagebrokersuchasAcOveMQ

•  AcOveMQcanbeeasilyconfiguredinaSpringApplicaOonContext

•  Versions>4.1evenprovidean<amq/>XMLnamespaceforDSL‐likeconfiguraOon

Page 28: Effective out-of-container Integration Testing

AcOveMQSpringConfiguraOon<bean id="connectionFactory" class= "org.apache.activemq.spring.ActiveMQConnectionFactory” p:brokerURL="vm://localhost?broker.persistent=false" />

<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate" p:connectionFactory-ref="connectionFactory" />

Page 29: Effective out-of-container Integration Testing

SMTPServer

•  UseDumbster'sSimpleSmtpServer– Configurableportnumber

– Tracksallmailssent– Providesmethodsforretrieving•  Numberofmailssent

•  Individualmails•  Mailheaders

•  Mailbody

Page 30: Effective out-of-container Integration Testing

AbstractEmailSenderTest(1/2)public abstract class AbstractEmailSenderTest {

protected SimpleSmtpServer server;

@Before public void startSmtpServer() { server = SimpleSmtpServer.start(getSmtpPort()); }

@After public void stopSmtpServer() { server.stop(); }

protected abstract int getSmtpPort();

Page 31: Effective out-of-container Integration Testing

AbstractEmailSenderTest(2/2) protected void assertNumEmailsSent(SimpleSmtpServer server, int expected) { assertEquals("Verifying number of e-mails sent.”, expected, server.getReceivedEmailSize()); }

protected void assertEmailHeaderValue(SmtpMessage email, String header, String expected) { assertEquals(expected, email.getHeaderValue(header)); }

protected void assertEmailBodyContains(SmtpMessage email, String expected) { assertTrue(email.getBody().contains(expected)); }

Page 32: Effective out-of-container Integration Testing

PlainEmailSenderTest(1/2)@ContextConfiguration("/applicationContext.xml")public class PlainEmailSenderTest extends AbstractEmailSenderTest {

@Autowired private PlainEmailSenderImpl plainEmailSender;

@Override protected int getSmtpPort() { return 62525; }

Page 33: Effective out-of-container Integration Testing

PlainEmailSenderTest(2/2)@Testpublic void plainEmail() throws Exception { plainEmailSender.sendSimpleEmail(recipientEmail);

assertNumEmailsSent(server, 1);

SmtpMessage email = (SmtpMessage) server.getReceivedEmail().next();

assertEmailHeaderValue(email, "Subject", "testing"); assertEmailHeaderValue(email, "From", "[email protected]"); assertEmailBodyContains(email, "This is a test email");}

Page 34: Effective out-of-container Integration Testing

FTPServer

•  UseMockFtpServer's– FakeFtpServer•  Virtualorin‐memoryfilesystem•  Useraccountsandpermissions

– StubFtpServer•  Low‐levelFTPservercommands

Page 35: Effective out-of-container Integration Testing

ServletContainer

•  UseJenyorTomcatinembeddedmode•  ConfigureJenywithMavenandexecutethejeny:rungoal

Page 36: Effective out-of-container Integration Testing

ConfiguraOonTips

•  ExternalizeconnecOonse_ngsinJavaProperOesfiles

•  DefinedifferentProperOesfilesforproducOonandtesOng

•  UseSpring'sPropertyPlaceholderConfigureror<context:property‐placeholder>forpropertyreplacement

Page 37: Effective out-of-container Integration Testing

AvoidHostname&PortCollisions

•  PayspecialanenOontohostnamesandports– SMTP

– FTP– Servletcontainer

•  ConsiderusingsomethinglikeSpring'sFreePortScanner

Page 38: Effective out-of-container Integration Testing

EmbeddedHSQLdatabasewithSpring’s<jdbc/>namespace

HibernateEventRepositoryTests

Demo

Page 39: Effective out-of-container Integration Testing

JMSwithanin‐memoryAcOveMQmessagebroker

JmsNamespaceTest

Demo

Page 40: Effective out-of-container Integration Testing

EmailwithDumbster’sSimpleSmtpServer

PlainEmailSenderTest

Demo

Page 41: Effective out-of-container Integration Testing

EmbeddedJenyServletcontainer

AbstractJeKyTest

Demo

Page 42: Effective out-of-container Integration Testing

FurtherResources•  HSQLDB

–  hnp://hsqldb.org•  H2

–  hnp://www.h2database.com

•  AcOveMQ–  hnp://acOvemq.apache.org

•  Dumbster–  hnp://quintanaso+.com/dumbster

•  MockFtpServer–  hnp://mock+pserver.sourceforge.net

•  Jeny–  hnp://jeny.codehaus.org

•  Tomcat–  hnp://tomcat.apache.org

Page 43: Effective out-of-container Integration Testing

Q&A

SamBrannen

sam.brannen[at]swi+mind[dot]com

hnp://www.swi+mind.com

hnp://twiner.com/sam_brannen

“SpringinaNutshell” hnp://oreilly.com/catalog/9780596801946 availablefromO’Reillyin2011