Bevezetés a várakozásba

1. Bemutatkozás

Az aszinkron rendszerek gyakori problémája, hogy nehéz számukra olyan olvasható teszteket írni, amelyek az üzleti logikára összpontosítanak, és nincsenek szennyezve szinkronizálással, időtúllépéssel és egyidejűség-vezérléssel.

Ebben a cikkben megnézzük Várakozás - olyan könyvtár, amely egyszerű tartományspecifikus nyelvet (DSL) biztosít az aszinkron rendszerek teszteléséhez.

A Várakozással megtehetjük fejezze ki a rendszerrel szemben támasztott elvárásainkat egy könnyen olvasható DSL-ben.

2. Függőségek

Ki kell egészítenünk a várakozási függőségeket pom.xml.

A várakozás könyvtár a legtöbb felhasználási esetre elegendő lesz. Abban az esetben, ha proxy alapú feltételeket akarunk használni, nekünk is meg kell adnunk a várakozás-proxy könyvtár:

 org.awaitility awaitility 3.0.0 teszt org.awaitility awaitility-proxy 3.0.0 teszt 

Megtalálja a várakozás és várakozás-proxy könyvtárak a Maven Central-on.

3. Aszinkron szolgáltatás létrehozása

Írjunk egy egyszerű aszinkron szolgáltatást és teszteljük:

public class AsyncService {private final int KÉSLELTETÉS = 1000; privát döntő int INIT_DELAY = 2000; privát AtomicLong érték = új AtomicLong (0); private Executor végrehajtó = Executors.newFixedThreadPool (4); privát volatile boolean inicializált = hamis; void inicializálás () {végrehajtó.execute (() -> {alvás (INIT_DELAY); inicializált = igaz;}); } logikai isInitialized () {return inicializált; } void addValue (hosszú val) {dobIfNotInitialized (); végrehajtó.execute (() -> {alvás (KÉSLELTETÉS); érték.addAndGet (val);}); } public long getValue () {dobIfNotInitialized (); return value.longValue (); } private void sleep (int késés) {próbáld ki {Thread.sleep (késleltetés); } catch (InterruptedException e) {}} private void throwIfNotInitialized () {if (! inicializálva) {dobjon új IllegalStateException-t ("A szolgáltatás nincs inicializálva"); }}}

4. Várakozással történő tesztelés

Most hozzuk létre a teszt osztályt:

public class AsyncServiceLongRunningManualTest {private AsyncService asyncService; @ Nyilvános void előtt setUp () {asyncService = új AsyncService (); } // ...}

Tesztünk ellenőrzi, hogy szolgáltatásunk inicializálása egy meghatározott időkorláton belül (alapértelmezett 10 másodpercen belül) megtörténik-e a inicializálni módszer.

Ez a tesztesemény csupán arra vár, hogy a szolgáltatás inicializálási állapota megváltozzon, vagy a ConditionTimeoutException ha az állapotváltozás nem következik be.

A státuszt a Hívható amely meghatározott időközönként (100 ms alapértelmezett) lekérdezi szolgáltatásunkat egy meghatározott kezdeti késleltetés (alapértelmezett 100 ms) után. Itt az alapértelmezett beállításokat használjuk az időtúllépéshez, az intervallumhoz és a késleltetéshez:

asyncService.initialize (); wait () .until (asyncService :: isInitialized);

Itt használjuk várják - az egyik statikus módszere Várakozás osztály. Visszaadja az a példányát ConditionFactory osztály. Használhatunk más módszereket is, például adott az olvashatóság növelése érdekében.

Az alapértelmezett időzítési paraméterek a Várakozás osztály:

Awaitility.setDefaultPollInterval (10, TimeUnit.MILLISECONDS); Awaitility.setDefaultPollDelay (Duration.ZERO); Awaitility.setDefaultTimeout (Időtartam.ONE_MINUTE);

Itt láthatjuk a Időtartam osztály, amely hasznos állandókat biztosít a leggyakrabban használt időszakokra.

Azt is megtehetjük adjon meg egyedi időzítési értékeket mindegyikhez várják hívás. Arra számítunk, hogy az inicializálás legfeljebb öt másodperc múlva, de legalább 100 ms után történik meg 100 ms lekérdezési intervallummal:

asyncService.initialize (); wait () .atLeast (Duration.ONE_HUNDRED_MILLISECONDS) .atMost (Duration.FIVE_SECONDS) .with () .pollInterval (Duration.ONE_HUNDRED_MILLISECONDS) .until (asyncService :: isInitialized);

Érdemes megemlíteni, hogy a ConditionFactory további módszereket tartalmaz, mint például val vel, azután, és, adott. Ezek a módszerek nem tesznek semmit, és csak visszatérnek ez, de hasznosak lehetnek a tesztfeltételek olvashatóságának javítása érdekében.

5. A Matchers használata

A várakozás lehetővé teszi a hamcrest párosok, hogy ellenőrizzék egy kifejezés eredményét. Például ellenőrizhetjük, hogy a mi hosszú értéke a várakozásoknak megfelelően megváltozik a hozzáadott érték módszer:

asyncService.initialize (); wait () .until (asyncService :: isInitialized); hosszú érték = 5; asyncService.addValue (érték); várjon () .until (asyncService :: getValue, equalTo (érték));

Vegye figyelembe, hogy ebben a példában az elsőt használtuk várják hívjon, hogy megvárja, amíg a szolgáltatás inicializálódik. Egyébként a getValue módszer dobna egy IllegalStateException.

6. A kivételeket figyelmen kívül hagyva

Néha előfordul olyan helyzet, hogy egy módszer kivételt vet az aszinkron munka elvégzése előtt. Szolgáltatásunkban felhívás lehet a getValue metódus a szolgáltatás inicializálása előtt.

A várakozás lehetőséget nyújt a kivétel figyelmen kívül hagyására anélkül, hogy elbukna egy teszten.

Ellenőrizzük például, hogy a getValue eredmény egyenlő nulla inicializálás után, figyelmen kívül hagyva IllegalStateException:

asyncService.initialize (); adott (). ignoreException (IllegalStateException.class) .await (). atMost (Duration.FIVE_SECONDS) .atLeast (Duration.FIVE_HUNDRED_MILLISECONDS) .until (asyncService :: getValue, equalTo (0L));

7. A Proxy használata

Amint azt a 2. szakasz leírja, bele kell foglalnunk várakozás-proxy proxy alapú feltételek használatához. A proxynek az az elképzelése, hogy valós módszereket igényeljen a feltételek megvalósítása nélkül Hívható vagy lambda kifejezés.

Használjuk a AwaitilityClassProxy.to statikus módszer ennek ellenőrzésére AsyncService inicializálva van:

asyncService.initialize (); várja () .untilCall (to (asyncService) .isInitialized (), egyenlőTo (igaz));

8. Mezők elérése

A várakozás még a privát mezőkhöz is hozzáférhet, hogy állításokat hajtson végre rajtuk. A következő példában egy másik módot láthatunk szolgáltatásunk inicializálási állapotának megszerzésére:

asyncService.initialize (); await () .until (fieldIn (asyncService) .ofType (boolean.class) .andWithName ("inicializált"), equalTo (true));

9. Következtetés

Ebben a gyors bemutatóban bemutattuk az Awaitility könyvtárat, megismerkedtünk az aszinkron rendszerek teszteléséhez szükséges alap DSL-lel, és megláttunk néhány olyan fejlett funkciót, amelyek rugalmassá és könnyen használhatóvá teszik a könyvtárat valós projektekben.

Mint mindig, minden kódpélda elérhető a Githubon.