Tavaszi kötegelt feladat tesztelése

1. Bemutatkozás

A többi tavaszi alkalmazással ellentétben a kötegelt feladatok tesztelése bizonyos sajátos kihívásokkal jár, főleg a feladatok végrehajtásának aszinkron jellege miatt.

Ebben az oktatóanyagban megvizsgáljuk a Spring Batch feladat tesztelésének különböző alternatíváit.

2. Szükséges függőségek

Használjuk rugós-bakancs-indító-tétel, ezért először állítsuk be a szükséges függőségeket a pom.xml:

 org.springframework.boot spring-boot-starter-batch 2.1.9.RELEASE org.springframework.boot spring-boot-starter-test 2.1.9.RELEASE test org.springframework.batch spring-batch-test 4.2.0.RELEASE teszt 

Bele is foglaltuk a tavasz-bút-starter-teszt és tavasz-tétel-teszt amelyek néhány szükséges segítő módszert, hallgatót és futót hoznak be a Spring Batch alkalmazások teszteléséhez.

3. A tavaszi kötegelt feladat meghatározása

Készítsünk egy egyszerű alkalmazást annak bemutatására, hogy a Spring Batch hogyan oldja meg a tesztelés néhány kihívását.

Alkalmazásunk kétlépcsős Munka amely egy CSV bemeneti fájlt olvas fel strukturált könyv információkkal, és kiadja a könyveket és a könyv részleteit.

3.1. A munka lépéseinek meghatározása

A két későbbi Lépéss kivonat konkrét információkat BookRecords majd ezeket térképezze fel Könyvs (1. lépés) és BookDetails (2. lépés):

@Bean nyilvános 1. lépés (ItemReader csvItemReader, ItemWriter jsonItemWriter) dobja az IOException {return stepBuilderFactory .get ("step1") parancsot. chunk (3) .reader (csvItemReader) .processor (bookItemProcessor ()) .writer (jsonItemWriter) .build (); } @Bean public 2. lépés: (ItemReader csvItemReader, ItemWriter listItemWriter) {return stepBuilderFactory .get ("2. lépés"). chunk (3) .reader (csvItemReader) .processor (bookDetailsItemProcessor ()) .writer (listItemWriter) .build (); }

3.2. Az Input Reader és az Output Writer meghatározása

Nézzük most konfigurálja a CSV fájl bemeneti olvasót a segítségével FlatFileItemReader hogy a strukturált könyvinformációk sorozatlanná váljanak BookRecord tárgyak:

privát statikus végső karakterlánc [] TOKENS = {"könyvnév", "könyvíró", "könyvformátum", "isbn", "közzétételi év"}; @Bean @StepScope public FlatFileItemReader csvItemReader (@Value ("# {jobParameters ['file.input']}" ") Karakterlánc bemenet) {FlatFileItemReaderBuilder builder = new FlatFileItemReaderBuilder (); FieldSetMapper bookRecordFieldSetMapper = new BookRecordFieldSetMapper (); return builder .name ("bookRecordItemReader") .resource (new FileSystemResource (input)) .delimited () .names (TOKENS) .fieldSetMapper (bookRecordFieldSetMapper) .build (); }

Van néhány fontos dolog ebben a meghatározásban, amelyek kihatással lesznek a tesztelés módjára.

Először is, jegyzeteltük a FlatItemReader bab @StepScope, és ennek eredményeként, ez az objektum megosztja az élettartamát StepExecution.

Ez lehetővé teszi számunkra a dinamikus értékek futtatását futás közben is, hogy tovább tudjuk adni a bemeneti fájlunkat a JobParameters a 4. sorban. Ezzel szemben a BookRecordFieldSetMapper fordításkor vannak konfigurálva.

Ezután hasonlóan definiáljuk a JsonFileItemWriter output író:

@Bean @StepScope public JsonFileItemWriter jsonItemWriter (@Value ("# {jobParameters ['file.output']}" ") Karakterlánc kimenet) dobja az IOException {JsonFileItemWriterBuilder builder = new JsonFileItemWriterBuilder (); JacksonJsonObjectMarshaller marshaller = új JacksonJsonObjectMarshaller (); return builder .name ("bookItemWriter") .jsonObjectMarshaller (marshaller) .resource (new FileSystemResource (output)) .build (); } 

A másodikra Lépés, egy Spring Batch által biztosított ListItemWriter hogy csak a memóriában lévő dolgokat dobja ki a memóriába.

3.3. Az egyedi meghatározása JobLauncher

Ezután tiltsuk le az alapértelmezettet Munka a Spring Boot Batch konfigurációjának elindítása beállítással spring.batch.job.enabled = hamis miénkben alkalmazás.tulajdonságok.

Konfiguráljuk a sajátunkat JobLauncher hogy átadjon egy szokást JobParameters például a Munka:

@SpringBootApplication public class SpringBatchApplication végrehajtja a CommandLineRunner {// autowired jobLauncher és transformBooksRecordsJob @Value ("$ {file.input}") privát karakterlánc-bevitelt; @Value ("$ {file.output}") privát karakterlánc kimenet; A @Orride public void run (String ... args) kivételt dob ​​{JobParametersBuilder paramsBuilder = new JobParametersBuilder (); paramsBuilder.addString ("file.input", input); paramsBuilder.addString ("file.output", output); jobLauncher.run (transformBooksRecordsJob, paramsBuilder.toJobParameters ()); } // egyéb módszerek (fő stb.)} 

4. A tavaszi kötegelt munka tesztelése

A tavasz-tétel-teszt A függőség olyan hasznos segítő módszereket és hallgatókat kínál, amelyek felhasználhatók a Spring Batch kontextus konfigurálására a tesztelés során.

Hozzunk létre egy alapstruktúrát a tesztünkhöz:

@RunWith (SpringRunner.class) @SpringBatchTest @EnableAutoConfiguration @ContextConfiguration (class = {SpringBatchConfiguration.class}) @TestExecutionListeners ({DependencyInjectionTestExecutionListener.class, DirtiesContextTestExt_ Class_Test_City_ Class_Test} egyéb tesztállandók @Autowired private JobLauncherTestUtils jobLauncherTestUtils; @Autowired private JobRepositoryTestUtils jobRepositoryTestUtils; @A public public void cleanUp () {jobRepositoryTestUtils.removeJobExecutions (); } private JobParameters defaultJobParameters () {JobParametersBuilder paramsBuilder = new JobParametersBuilder (); paramsBuilder.addString ("file.input", TEST_INPUT); paramsBuilder.addString ("file.output", TEST_OUTPUT); return paramsBuilder.toJobParameters (); } 

A @SpringBatchTest annotáció biztosítja a JobLauncherTestUtils és JobRepositoryTestUtils segítő osztályok. Használjuk őket a Munka és Lépéss tesztjeinkben.

Az alkalmazás használja Tavaszi indítás automatikus konfigurálása, amely lehetővé teszi az alapértelmezett memóriakártyát JobRepository. Ennek eredményeként Több teszt futtatása ugyanabban az osztályban minden tesztfutás után megtisztító lépést igényel.

Végül, ha több tesztet akarunk lefuttatni több tesztosztályból, akkor piszkosnak kell jelölnünk a környezetünket. Erre azért van szükség, hogy elkerüljük a többiek ütközését JobRepository ugyanazon adatforrást használó példányok.

4.1. Az end-to-end tesztelése Munka

Az első dolog, amit tesztelünk, egy teljes végponttól végpontig Munka kis adatkészletű bemenettel.

Ezután összehasonlíthatjuk az eredményeket egy várható tesztkimenettel:

@Test public void givenReferenceOutput_whenJobExecuted_thenSuccess () dobja a Kivételt {// adott FileSystemResource vártResult = új FileSystemResource (EXPECTED_OUTPUT); FileSystemResource actualResult = új FileSystemResource (TEST_OUTPUT); // amikor JobExecution jobExecution = jobLauncherTestUtils.launchJob (defaultJobParameters ()); JobInstance actualJobInstance = jobExecution.getJobInstance (); ExitStatus actualJobExitStatus = jobExecution.getExitStatus (); // majd assertThat (actualJobInstance.getJobName (), is ("transformBooksRecords")); assertThat (actualJobExitStatus.getExitCode (), van ("TELJES"); AssertFile.assertFileEquals (várható eredmény, tényleges eredmény); }

A Spring Batch Test hasznos fájl-összehasonlító módszer a kimenetek igazolásához a AssertFile osztály.

4.2. Az egyes lépések tesztelése

Néha meglehetősen drága a teljes tesztelése Munka végponttól végig, és ezért van értelme tesztelni az egyént Lépések helyette:

@Test public void givenReferenceOutput_whenStep1Executed_thenSuccess () dobja a Kivételt {// adott FileSystemResource vártResult = új FileSystemResource (EXPECTED_OUTPUT); FileSystemResource actualResult = új FileSystemResource (TEST_OUTPUT); // amikor JobExecution jobExecution = jobLauncherTestUtils.launchStep ("step1", defaultJobParameters ()); Gyűjtemény actualStepExecutions = jobExecution.getStepExecutions (); ExitStatus actualJobExitStatus = jobExecution.getExitStatus (); // majd assertThat (actualStepExecutions.size (), is (1)); assertThat (actualJobExitStatus.getExitCode (), van ("TELJES"); AssertFile.assertFileEquals (várható eredmény, tényleges eredmény); } @Test public void whenStep2Executed_thenSuccess () {// when JobExecution jobExecution = jobLauncherTestUtils.launchStep ("step2", defaultJobParameters ()); Collection actualStepExecutions = jobExecution.getStepExecutions (); ExitStatus actualExitStatus = jobExecution.getExitStatus (); // majd assertThat (actualStepExecutions.size (), is (1)); assertThat (actualExitStatus.getExitCode (), van ("TELJES")); actualStepExecutions.forEach (stepExecution -> {assertThat (stepExecution.getWriteCount (), is (8));}); }

Figyelje meg használjuk a launchStep módszer konkrét lépések kiváltására.

Emlékezz arra mi is megterveztük a mi ItemReader és ItemWriter hogy dinamikus értékeket használjon futás közben, ami azt jelenti átadhatjuk az I / O paramétereinket a JobExecution(9. és 23. sor).

Elsőre Lépés teszt során összehasonlítjuk a tényleges kimenetet egy várható kimenettel.

Másrészről, a második tesztben ellenőrizzük a StepExecution a várható írott tételekért.

4.3. Lépcsőzetes alkatrészek tesztelése

Most teszteljük a FlatFileItemReader. Emlékezzünk vissza, hogy kitettük @StepScope babot, ezért ehhez a Spring Batch dedikált támogatását akarjuk használni:

// korábban bejegyzett itemReader @Test public void givenMockedStep_whenReaderCalled_thenSuccess () dobja a Kivételt {// adott StepExecution stepExecution = MetaDataInstanceFactory .createStepExecution (defaultJobParameters ()); // amikor StepScopeTestUtils.doInStepScope (stepExecution, () -> {BookRecord bookRecord; itemReader.open (stepExecution.getExecutionContext ()); while ((bookRecord = itemReader.read ())! = null) {// majd assertThat (bookRecord .getBookName (), is ("Foundation")); assertThat (bookRecord.getBookAuthor (), is ("Asimov I.")); assertThat (bookRecord.getBookISBN (), is ("ISBN 12839")); assertThat ( bookRecord.getBookFormat (), is ("keménytáblás")); assertThat (bookRecord.getPublishingYear (), is ("2018"));} itemReader.close (); return null;}); }

A MetadataInstanceFactory létrehoz egy szokást StepExecution ami a Step-hatókörünk beadásához szükséges ItemReader.

Emiatt, segítségével ellenőrizhetjük az olvasó viselkedését doInTestScope módszer.

Ezután teszteljük a JsonFileItemWriter és ellenőrizze a kimenetét:

@Test public void givenMockedStep_whenWriterCalled_thenSuccess () dobja a Kivételt {// adott FileSystemResource vártResult = új FileSystemResource (EXPECTED_OUTPUT_ONE); FileSystemResource actualResult = új FileSystemResource (TEST_OUTPUT); Book demoBook = new Book (); demoBook.setAuthor ("Grisham J."); demoBook.setName ("A cég"); StepExecution stepExecution = MetaDataInstanceFactory .createStepExecution (alapértelmezettJobParameters ()); // amikor StepScopeTestUtils.doInStepScope (stepExecution, () -> {jsonItemWriter.open (stepExecution.getExecutionContext ()); jsonItemWriter.write (Arrays.asList (demoBook)); jsonItemWriter.close (); return null; // majd AssertFile.assertFileEquals (várható eredmény, tényleges eredmény); } 

A korábbi tesztekkel ellentétben most teljes mértékben ellenőrizzük a tesztobjektumainkat. Ennek eredményeként mi vagyunk a felelősek az I / O folyamok megnyitásáért és bezárásáért.

5. Következtetés

Ebben az oktatóanyagban megvizsgáltuk a Spring Batch feladat tesztelésének különböző megközelítéseit.

Az end-to-end tesztelés ellenőrzi a feladat teljes végrehajtását. Az egyes lépések tesztelése segíthet összetett forgatókönyvekben.

Végül, amikor a lépcsős hatókörű komponensekről van szó, használhatunk egy csomó segítő módszert, amelyet a tavasz-tétel-teszt. Segíteni fognak bennünket a Spring Batch domain objektumok elkábításában és gúnyolódásában.

Szokás szerint felfedezhetjük a teljes kódbázist a GitHubon.


$config[zx-auto] not found$config[zx-overlay] not found