Serenity BDD s Spring i JBehave

1. Uvod

Prethodno smo uveli Serenity BDD okvir.

U ovom ćemo članku predstaviti kako integrirati Serenity BDD s Springom.

2. Ovisnost Mavena

Da bismo omogućili Serenity u našem proljetnom projektu, moramo dodati spokoj-jezgra i vedrina-proljeće prema pom.xml:

 test net.serenity-bdd serenity-core 1.4.0 test net.serenity-bdd serenity-spring 1.4.0 test 

Također moramo konfigurirati serenity-maven-plugin, što je važno za generiranje izvještaja o testovima spokojstva:

 net.serenity-bdd.maven.plugins serenity-maven-plugin 1.4.0 serenity-reports post-integracija-test agregat 

3. Proljetna integracija

Proljetni integracijski test treba @RunWithSpringJUnit4ClassRunner. Ali ne možemo koristiti test trkač izravno sa Serenity, jer testovi Serenity trebaju biti pokrenuti SerenityRunner.

Za testove sa Serenity možemo koristiti SpringIntegrationMethodRule i SpringIntegrationClassRule kako bi se omogućilo ubrizgavanje.

Naš ćemo se test temeljiti na jednostavnom scenariju: ako se doda broj, kada se doda drugi broj, a zatim se vraća zbroj.

3.1. SpringIntegrationMethodRule

SpringIntegrationMethodRule je Pravilo metode primijenjene na metode ispitivanja. Proljetni kontekst bit će izgrađen prije @Prije i poslije @BeforeClass.

Pretpostavimo da imamo svojstvo ubrizgavanja u svoj grah:

 4 

Sad dodajmo SpringIntegrationMethodRule kako bismo omogućili ubrizgavanje vrijednosti u našem testu:

@RunWith (SerenityRunner.class) @ContextConfiguration (locations = "classpath: adder-beans.xml") javna klasa AdderMethodRuleIntegrationTest {@Rule public SpringIntegrationMethodRule springMethodIntegration = new SpringIntegrationMethodRule (); @Steps private AdderSteps adderSteps; @Value ("# {props ['adder']}") private int adder; @Test javna praznina givenNumber_whenAdd_thenSummedUp () {adderSteps.givenNumber (); adderSteps.whenAdd (adder); adderSteps.thenSummedUp (); }}

Također podržava bilješke na razini metode proljetni test. Ako neka metoda ispitivanja zaprlja kontekst testa, možemo označiti @DirtiesContext na tome:

@RunWith (SerenityRunner.class) @FixMethodOrder (MethodSorters.NAME_ASCENDING) @ContextConfiguration (classes = AdderService.class) javna klasa AdderMethodDirtiesContextIntegrationTest {@Steps private AdderServiceSteps adderSerps; @Rule public SpringIntegrationMethodRule springIntegration = new SpringIntegrationMethodRule (); @DirtiesContext @Test public void _0_givenNumber_whenAddAndAccumulate_thenSummedUp () {adderServiceSteps.givenBaseAndAdder (randomInt (), randomInt ()); adderServiceSteps.whenAccumulate (); adderServiceSteps.summedUp (); adderServiceSteps.whenAdd (); adderServiceSteps.sumWrong (); } @Test public void _1_givenNumber_whenAdd_thenSumWrong () {adderServiceSteps.whenAdd (); adderServiceSteps.sumWrong (); }}

U gornjem primjeru, kada pozivamo adderServiceSteps.whenAccumulate (), polje osnovnog broja polja @Servis ubrizgano u adderServiceSteps bit će promijenjeno:

@ContextConfiguration (classes = AdderService.class) javna klasa AdderServiceSteps {@Autowired private AdderService adderService; private int givenNumber; privatna int baza; privatna int suma; javna praznina givenBaseAndAdder (int baza, int zbrajač) {this.base = baza; adderService.baseNum (baza); this.givenNumber = sabirač; } javna void kadaAdd () {sum = adderService.add (givenNumber); } javna praznina summedUp () {assertEquals (baza + zadaniBroj, zbroj); } javna praznina sumWrong () {assertNotEquals (baza + zadaniBroj, zbroj); } javna prazna kadaAccumulate () {sum = adderService.accumulate (givenNumber); }}

Točnije, zbroj dodijelimo osnovnom broju:

@Service javna klasa AdderService {private int num; javna praznina baseNum (int baza) {this.num = baza; } public int currentBase () {return broj; } public int add (int adder) {return this.num + adder; } javni int akumulirati (int adder) {return this.num + = adder; }}

U prvom testu _0_givenNumber_whenAddAndAccumulate_thenSummedUp, osnovni broj se mijenja, što čini kontekst prljavim. Kad pokušamo dodati još jedan broj, nećemo dobiti očekivani zbroj.

Primijetite da čak i ako smo prvi test označili s @DirtiesContext, drugi test još uvijek utječe: nakon dodavanja zbroj je i dalje pogrešan. Zašto?

Sada, dok se obrađuje razina metode @DirtiesContext, Serenityjeva proljetna integracija samo ponovno gradi testni kontekst za trenutnu testnu instancu. Temeljni kontekst ovisnosti u @ Koraci neće se obnoviti.

Da bismo zaobišli ovaj problem, možemo ubrizgati @Servis u našoj trenutnoj testnoj instanci i uslugu učinimo eksplicitnom ovisnošću od @ Koraci:

@RunWith (SerenityRunner.class) @FixMethodOrder (MethodSorters.NAME_ASCENDING) @ContextConfiguration (classes = AdderService.class) javna klasa AdderMethodDirtiesContextDependencyWorkaroundIntegrationTest {private AdderContectorpsDependencyStenderStropsDependencyDependencyDependencyDependencySenderStartSectorSpace; @Autowired privatni AdderService adderService; @ Prije javne void init () {adderSteps = new AdderConstructorDependencySteps (adderService); } // ...}
javna klasa AdderConstructorDependencySteps {private AdderService adderService; javni AdderConstructorDependencySteps (AdderService adderService) {this.adderService = adderService; } // ...}

Ili korak inicijalizacije stanja možemo staviti u @Prije odjeljak kako bi se izbjegao prljavi kontekst. No, takva vrsta rješenja možda neće biti dostupna u nekim složenim situacijama.

@RunWith (SerenityRunner.class) @FixMethodOrder (MethodSorters.NAME_ASCENDING) @ContextConfiguration (classes = AdderService.class) javna klasa AdderMethodDirtiesContextInitWorkaroundIntegrationTest {@Steps private AdderServiceStepstepspsServiceStepstepsterServiceStepstepspsServiceStepstepspsServiceStepstepsps; @Before public void init () {adderServiceSteps.givenBaseAndAdder (randomInt (), randomInt ()); } // ...}

3.2. SpringIntegrationClassRule

Da bismo omogućili napomene na razini razreda, trebali bismo koristiti SpringIntegrationClassRule. Recimo da imamo slijedeće ispitne satove; svaka zaprlja kontekst:

@RunWith (SerenityRunner.class) @ContextConfiguration (classes = AdderService.class) javna statička apstraktna klasa Base {@Steps AdderServiceSteps adderServiceSteps; @ClassRule public static SpringIntegrationClassRule springIntegrationClassRule = new SpringIntegrationClassRule (); void whenAccumulate_thenSummedUp () {adderServiceSteps.whenAccumulate (); adderServiceSteps.summedUp (); } void whenAdd_thenSumWrong () {adderServiceSteps.whenAdd (); adderServiceSteps.sumWrong (); } void whenAdd_thenSummedUp () {adderServiceSteps.whenAdd (); adderServiceSteps.summedUp (); }}
@DirtiesContext (classMode = AFTER_CLASS) javna statička klasa DirtiesContextIntegrationTest proširuje bazu {@Test javna praznina givenNumber_whenAdd_thenSumWrong () {super.whenAdd_thenSummedUp (); adderServiceSteps.givenBaseAndAdder (randomInt (), randomInt ()); super.whenAccumulate_thenSummedUp (); super.whenAdd_thenSumWrong (); }}
@DirtiesContext (classMode = AFTER_CLASS) javna statička klasa AnotherDirtiesContextIntegrationTest proširuje bazu {@Test javna praznina givenNumber_whenAdd_thenSumWrong () {super.whenAdd_thenSummedUp (); adderServiceSteps.givenBaseAndAdder (randomInt (), randomInt ()); super.whenAccumulate_thenSummedUp (); super.whenAdd_thenSumWrong (); }}

U ovom primjeru, sve implicitne injekcije bit će obnovljene za razinu klase @DirtiesContext.

3.3. SpringIntegrationSerenityRunner

Postoji prikladna klasa SpringIntegrationSerenityRunner koji automatski dodaje oba gornja pravila integracije. S ovim pokretačem možemo pokrenuti gornje testove kako bismo izbjegli specificiranje metode ili pravila ispitivanja klase u našem testu:

@RunWith (SpringIntegrationSerenityRunner.class) @ContextConfiguration (locations = "classpath: adder-beans.xml") javna klasa AdderSpringSerenityRunnerIntegrationTest {@Steps private AdderSteps adderSteps; @Value ("# {props ['adder']}") private int adder; @Test javna praznina givenNumber_whenAdd_thenSummedUp () {adderSteps.givenNumber (); adderSteps.whenAdd (adder); adderSteps.thenSummedUp (); }}

4. SpringMVC integracija

U slučajevima kada samo moramo testirati SpringMVC komponente sa Serenity, možemo ih jednostavno iskoristiti RestAssuredMockMvc u uvjerenju umjesto vedrina-proljeće integracija.

4.1. Ovisnost Mavena

Moramo dodati i uvjerenu ovisnost spring-mock-mvc na pom.xml:

 io.osigurano proljeće-mock-mvc 3.0.3 test 

4.2. RestAssuredMockMvc na djelu

Ajmo sada testirati sljedeći kontroler:

@RequestMapping (value = "/ adder", produce = MediaType.APPLICATION_JSON_UTF8_VALUE) @RestController javna klasa PlainAdderController {private final int currentNumber = RandomUtils.nextInt (); @GetMapping ("/ current") public int currentNum () {return currentNumber; } @PostMapping public int add (@RequestParam int num) {return currentNumber + num; }}

Možemo iskoristiti MVC uslužne programe za RestAssuredMockMvc kao ovo:

@RunWith (SerenityRunner.class) javna klasa AdderMockMvcIntegrationTest {@Before public void init () {RestAssuredMockMvc.standaloneSetup (new PlainAdderController ()); } @Steps AdderRestSteps koraci; @Test javna praznina givenNumber_whenAdd_thenSummedUp () baca iznimku {steps.givenCurrentNumber (); steps.whenAddNumber (randomInt ()); koraci.thenSummedUp (); }}

Tada se ostatak ne razlikuje od načina na koji koristimo budite uvjereni:

javna klasa AdderRestSteps {private MockMvcResponse mockMvcResponse; private int currentNum; @Step ("get the current number") javna praznina givenCurrentNumber () baca UnsupportedEncodingException {currentNum = Integer.valueOf (given () .when () .get ("/ adder / current") .mvcResult () .getResponse (). getContentAsString ()); } @Step ("dodavanje {0}") javna void kadaAddNumber (int num) {mockMvcResponse = given () .queryParam ("num", num) .when () .post ("/ adder"); currentNum + = num; } @Step ("dobio zbroj") javna void thenSummedUp () {mockMvcResponse .then () .statusCode (200) .body (jednakTo (currentNum + "")); }}

5. Serenity, JBehave i Spring

Podrška za integraciju Serenity Spring koristi neometano JBehave. Napišimo naš testni scenarij kao priču o JBehaveu:

Scenarij: Korisnik može poslati broj zbrajatelju i dobiti zbroj S obzirom na broj Kada dodam drugi broj 5 zbrajatelju Tada dobivam zbroj brojeva

Logiku možemo implementirati u a @Servis i izložiti radnje putem API-ja:

@RequestMapping (value = "/ adder", produce = MediaType.APPLICATION_JSON_UTF8_VALUE) @RestController javna klasa AdderController {private AdderService adderService; javni AdderController (AdderService adderService) {this.adderService = adderService; } @GetMapping ("/ current") public int currentNum () {return adderService.currentBase (); } @PostMapping public int add (@RequestParam int num) {return adderService.add (num); }}

Sada možemo napraviti test Serenity-JBehave uz pomoć RestAssuredMockMvc kako slijedi:

@ContextConfiguration (classes = {AdderController.class, AdderService.class}) javna klasa AdderIntegrationTest proširuje SerenityStory {@Autowired private AdderService adderService; @BeforeStory javna void init () {RestAssuredMockMvc.standaloneSetup (novi AdderController (adderService)); }}
javna klasa AdderStory {@Steps AdderRestSteps restSteps; @Given ("a number") javna praznina givenANumber () baca izuzetak {restSteps.givenCurrentNumber (); } @When ("Predajem još jedan broj $ num zbrajanju") javna void whenISubmitToAdderWithNumber (int num) {restSteps.whenAddNumber (num); } @Then ("Dobivam zbroj brojeva") public void thenIGetTheSum () {restSteps.thenSummedUp (); }}

Možemo samo obilježiti SerenityStory s @ContextConfiguration, tada je ubrizgavanje opruge omogućeno automatski. Ovo djeluje potpuno isto kao i @ContextConfiguration na @ Koraci.

6. Sažetak

U ovom smo članku govorili o tome kako integrirati Serenity BDD s Springom. Integracija nije sasvim savršena, ali definitivno se tamo stiže.

Kao i uvijek, potpuna implementacija može se naći na projektu GitHub.


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