Serenity BDD tavasszal és JBehave-vel

1. Bemutatkozás

Korábban bevezettük a Serenity BDD keretrendszert.

Ebben a cikkben bemutatjuk, hogyan integrálható a Serenity BDD a Spring-be.

2. Maven-függőség

Ahhoz, hogy a Serenity bekapcsolódhasson tavaszi projektünkbe, hozzá kell tennünk derű-mag és derű-tavasz hoz pom.xml:

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

Be kell állítanunk a serenity-maven-plugin, ami fontos a Serenity tesztjelentések készítéséhez:

 net.serenity-bdd.maven.plugins serenity-maven-plugin 1.4.0 serenity-jelentések az integráció utáni teszt összesítésről 

3. Tavaszi integráció

A tavaszi integrációs tesztnek meg kell @RunWithSpringJUnit4ClassRunner. De nem használhatjuk a tesztfutót közvetlenül a Serenity-vel, mivel a Serenity teszteket le kell futtatni SerenityRunner.

A Serenity tesztjeihez használhatjuk SpringIntegrationMethodRule és SpringIntegrationClassRule hogy lehetővé tegye az injekciót.

Tesztünket egyszerű forgatókönyvre alapozzuk: ha egy számot adunk hozzá, akkor adunk vissza egy összeget.

3.1. SpringIntegrationMethodRule

SpringIntegrationMethodRule egy MethodRule a vizsgálati módszerekre. A tavaszi kontextust már korábban felépítjük @Előtt és utána @Óra előtt.

Tegyük fel, hogy van olyan tulajdonságunk, hogy beadjunk egy babot:

 4 

Most tegyük hozzá SpringIntegrationMethodRule az értékbefecskendezés engedélyezéséhez a tesztünkben:

@RunWith (SerenityRunner.class) @ContextConfiguration (helyek = "classpath: adder-beans.xml") nyilvános osztály AdderMethodRuleIntegrationTest {@Rule public SpringIntegrationMethodRule springMethodIntegration = új SpringIntegrationMethodRule (); @Steps privát AdderSteps adderSteps; @Value ("# {props ['adder']}") privát int összegző; @Test public void givenNumber_whenAdd_thenSummedUp () {adderSteps.givenNumber (); adderSteps.whenAdd (összeadó); adderSteps.thenSummedUp (); }}

Támogatja a tavaszi teszt. Ha valamilyen vizsgálati módszer beszennyezi a tesztkörnyezetet, akkor jelölhetjük @DtiesContext Rajta:

@RunWith (SerenityRunner.class) @FixMethodOrder (MethodSorters.NAME_ASCENDING) @ContextConfiguration (class = AdderService.class) public class AdderMethodDtiesContextIntegrationTest {@Steps private AdderServiceSteps adderServiceSteps; @Rule public SpringIntegrationMethodRule springIntegration = új SpringIntegrationMethodRule (); @DtiesContext @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 (); }}

A fenti példában, amikor hivatkozunk adderServiceSteps.whenAccumulate (), az alapszám mezője @Szolgáltatás befecskendezték adderServiceSteps meg lesz változtatva:

@ContextConfiguration (class = AdderService.class) public class AdderServiceSteps {@Autowired private AdderService adderService; privát int adott szám; magán int bázis; privát int összeg; public void givenBaseAndAdder (int alap, int összegző) {this.base = alap; adderService.baseNum (alap); this.givenNumber = összeadó; } public void whenAdd () {összeg = adderService.add (megadottNumber); } public void summedUp () {assertEquals (alap + megadott szám, összeg); } public void sumWrong () {assertNotEquals (alap + megadott szám, összeg); } public void whenAccumulate () {sum = adderService.accumulate (givenNumber); }}

Pontosabban az összeget az alapszámhoz rendeljük:

@Service public class AdderService {private int num; public void baseNum (int alap) {this.num = alap; } public int currentBase () {return szám; } public int add (int összegző) {adja vissza ezt.szám + összeadó; } public int felhalmozódik (int összeadó) {adja vissza ezt.num + = összeadó; }}

Az első tesztben _0_givenNumber_whenAddAndAccumulate_thenSummedUp, az alapszám megváltozik, így a kontextus piszkos lesz. Amikor megpróbálunk újabb számot felvenni, nem kapunk várt összeget.

Vegyük észre, hogy még ha az első tesztet is jelöljük @DtiesContext, a második teszt továbbra is érintett: összeadás után az összeg még mindig téves. Miért?

Most, a feldolgozási módszer szintjén @DtiesContext, A Serenity tavaszi integrációja csak az aktuális tesztpéldány tesztkörnyezetét építi újra. A háttérben álló függőségi kontextus @Lépések nem fogják újjáépíteni.

A probléma kiküszöbölésére beadhatjuk a @Szolgáltatás a jelenlegi tesztpéldánkban, és a szolgáltatást tegye egyértelművé a @Lépések:

@RunWith (SerenityRunner.class) @FixMethodOrder (MethodSorters.NAME_ASCENDING) @ContextConfiguration (class = AdderService.class) public class AdderMethodDtiesContextDependencyWorkaroundIntegrationTest {private AdderConstructorDepsencySteps; @Autowired private AdderService adderService; @A nyilvános void előtt init () {adderSteps = new AdderConstructorDependencySteps (adderService); } // ...}
public class AdderConstructorDependencySteps {private AdderService adderService; public AdderConstructorDependencySteps (AdderService adderService) {this.adderService = adderService; } // ...}

Vagy tehetjük a feltétel inicializálási lépését a @Előtt szakasz a piszkos kontextus elkerülése érdekében. De ez a fajta megoldás bizonyos komplex helyzetekben nem biztos, hogy elérhető.

@RunWith (SerenityRunner.class) @FixMethodOrder (MethodSorters.NAME_ASCENDING) @ContextConfiguration (class = AdderService.class) public class AdderMethodDtiesContextInitWorkaroundIntegrationTest {@Steps private AdderServiceSteps adder; @A nyilvános void előtt init () {adderServiceSteps.givenBaseAndAdder (randomInt (), randomInt ()); } // ...}

3.2. SpringIntegrationClassRule

Az osztályszintű kommentárok engedélyezéséhez használnunk kell SpringIntegrationClassRule. Mondjuk, hogy a következő tesztosztályok vannak; mindegyik beszennyezi a kontextust:

@RunWith (SerenityRunner.class) @ContextConfiguration (class = AdderService.class) public static abstract class Base {@Steps AdderServiceSteps adderServiceSteps; @ClassRule nyilvános statikus 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 (); }}
@DtiesContext (classMode = AFTER_CLASS) nyilvános statikus osztály DirtiesContextIntegrationTest kiterjeszti a {@Test public void givenNumber_whenAdd_thenSumWrong () {super.whenAdd_thenSummedUp (); adderServiceSteps.givenBaseAndAdder (randomInt (), randomInt ()); super.whenAccumulate_thenSummedUp (); super.whenAdd_thenSumWrong (); }}
@DtiesContext (classMode = AFTER_CLASS) public static class újabb adderServiceSteps.givenBaseAndAdder (randomInt (), randomInt ()); super.whenAccumulate_thenSummedUp (); super.whenAdd_thenSumWrong (); }}

Ebben a példában minden implicit injekciót osztályszintre építenek @DtiesContext.

3.3. SpringIntegrationSerenityRunner

Van egy kényelmes osztály SpringIntegrationSerenityRunner amely automatikusan hozzáadja mindkét fenti integrációs szabályt. A fenti teszteket ezzel a futóval futtathatjuk, hogy elkerüljük a módszerünk vagy osztály tesztszabályainak megadását tesztünkben:

@RunWith (SpringIntegrationSerenityRunner.class) @ContextConfiguration (helyek = "classpath: adder-beans.xml") nyilvános osztály AdderSpringSerenityRunnerIntegrationTest {@Steps private AdderSteps adderSteps; @Value ("# {props ['adder']}") privát int összegző; @Test public void givenNumber_whenAdd_thenSummedUp () {adderSteps.givenNumber (); adderSteps.whenAdd (összeadó); adderSteps.thenSummedUp (); }}

4. SpringMVC integráció

Olyan esetekben, amikor csak a SpringMVC alkatrészeit kell Serenity-vel tesztelnünk, egyszerűen ki tudjuk használni RestAssuredMockMvc a nyugodt helyett derű-tavasz integráció.

4.1. Maven-függőség

Hozzá kell adnunk a megnyugtatott rugó-ál-mvc függőséget a pom.xml:

 io.pihenésbiztos rugós mock-mvc 3.0.3 teszt 

4.2. RestAssuredMockMvc akcióban

Most teszteljük a következő vezérlőt:

@RequestMapping (érték = "/ adder", = MediaType.APPLICATION_JSON_UTF8_VALUE) @RestController nyilvános osztály PlainAdderController {private final int currentNumber = RandomUtils.nextInt (); @GetMapping ("/ current") public int currentNum () {return currentNumber; } @ PostMapping public int add (@RequestParam int num) {return currentNumber + num; }}

Kihasználhatjuk az MVC gúnyos segédprogramjait RestAssuredMockMvc mint ez:

@RunWith (SerenityRunner.class) public class AdderMockMvcIntegrationTest {@Before public void init () {RestAssuredMockMvc.standaloneSetup (new PlainAdderController ()); } @Steps AdderRestSteps lépések; @Test public void givenNumber_whenAdd_thenSummedUp () dobja a Kivételt {steps.givenCurrentNumber (); steps.whenAddNumber (randomInt ()); steps.thenSummedUp (); }}

Ekkor a többi rész nem különbözik attól, ahogyan használjuk nyugodt:

public class AdderRestSteps {private MockMvcResponse mockMvcResponse; private int currentNum; A @Step ("az aktuális szám beolvasása") public void givenCurrentNumber () UnsupportedEncodingException {currentNum = Integer.valueOf (given () .when () .get ("/ addder / current") .mvcResult () .getResponse () dobja. getContentAsString ()); } @Step ("{0} hozzáadása") public void whenAddNumber (int num) {mockMvcResponse = megadott () .queryParam ("num", num) .when () .post ("/ addder"); currentNum + = szám; } @Step ("megkapta az összeget") public void thenSummedUp () {mockMvcResponse .then () .statusCode (200) .body (egyenlőTo (currentNum + "")); }}

5. Derű, JBehave és Spring

A Serenity tavaszi integrációs támogatása zökkenőmentesen működik a JBehave-lel. Írjuk meg teszt forgatókönyvünket JBehave-történetként:

Forgatókönyv: A felhasználó beküldhet egy számot az összeadóhoz, és megkapja az összeget. Számot ad meg, amikor újabb 5-ös számot adok be összegzőhöz, akkor a számok összegét kapom

A logikát a @Szolgáltatás és tegye közzé a műveleteket az API-k segítségével:

@RequestMapping (érték = "/ adder", = MediaType.APPLICATION_JSON_UTF8_VALUE) @RestController nyilvános osztály AdderController {private AdderService adderService; public 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); }}

Most elkészíthetjük a Serenity-JBehave tesztet a segítségével RestAssuredMockMvc alábbiak szerint:

@ContextConfiguration (class = {AdderController.class, AdderService.class}) public class AdderIntegrationTest kiterjeszti a SerenityStory {@Autowired private AdderService adderService; @BeforeStory public void init () {RestAssuredMockMvc.standaloneSetup (új AdderController (adderService)); }}
public class AdderStory {@Steps AdderRestSteps restSteps; @Given ("a number") public void givenANumber () dobja a {restSteps.givenCurrentNumber () kivételt; } @When ("Újabb számot adok be a $ num-hoz a kiegészítőkhöz") public void whenISubmitToAdderWithNumber (int num) {restSteps.whenAddNumber (num); } @Akkor ("a számok összegét kapom") public void thenIGetTheSum () {restSteps.thenSummedUp (); }}

Csak jelölni tudjuk SerenityStory val vel @ContextConfiguration, akkor a tavaszi befecskendezés automatikusan bekapcsol. Ez ugyanúgy működik, mint a @ContextConfiguration tovább @Lépések.

6. Összefoglalás

Ebben a cikkben kitértünk a Serenity BDD és a Spring integrálására. Az integráció nem egészen tökéletes, de mindenképpen elér.

Mint mindig, a teljes megvalósítás megtalálható a GitHub projektben.