středa 30. května 2012

Postřehy z integračního testování v Grails

Včera a dnes jsem začal s integračním testováním. Nevím, zda správně aplikuji filosofii integračních testů, ale hlavní je, že testuje to, co chci :) Napíšu sem pár postřehů, které jsem za 2 dny shromáždil a které mě překvapili:

  1. pro vytvoření mockup controlleru použijte normálně Controller controller = new Controller(). Problémem je však v tom, že pokud jednou vytvořený controller přiřadíte parametry či zavoláte akci, zůstanou parametry i odpovědi z akce v controlleru. A to i přesto, že vytvoříte novou instanci znova pomocí new Controller(). Tento problém jsem eliminoval tak, že jsem controller vlastnoručně vyčistil od "bordelu".
    /**
    * vyčistí controller pro další použití
    * musí se použít pokaždé, když chceme
    * vytvořit nový request
    * @param controller
    */
    private void clear(def controller) {
        controller.response?.reset()
        controller.params?.clear()
        controller.modelAndView?.clear()
    }
    Problém by šel líp vyřešit pomocí setUp() a tearDown(), ale protože testuji celý proces, tak jsem tyto metody nepoužil.

  2. pokud chcete otestovat vrácený model z controlleru, lze použít konstrukci controller.modelAndView.model.nazevModelu. Avšak konstrukce 
    [voucherInstance: voucherInstance, diagnosis: diagnosis, insuranceCompanyList: insuranceCompanyList]  
    nevrací žádný model (nevím, co přesně to vrací...). Stejně je to s konstrukcí 
    render(template: "detail", model: [voucherInstance: voucherInstance], status: 200)
    Zde to vrací vygenerovaný HTML snippet. Model vrací tato konstrukce: 
    render view: "edit", model: [voucherInstance: voucherInstance, diagnosis: diagnosis, insuranceCompanyList: insuranceCompanyList]

  3. používám IntelliJ jako IDE pro vývoj v Grails. Při testování jsem narazil na problém při debugování v controlleru, který používá metodu s closure.
    // akce v controlleru
    def edit() {
        checkVoucherById(params.id) {voucherInstance ->         
            // tady nemůžu vůbec stopnout zpracování
            render view: "edit", model: [voucherInstance: voucherInstance]
        }
    }


    // tohle je metoda, která bere jako parametr closure
    private checkVoucherById(id, closure) {
        Voucher voucherInstance = null
        try {
            id = id as long
            voucherInstance = voucherService.get(id)
            closure(voucherInstance)
        } catch (Throwable t) {
            // nějaká jiná akce
        }
    }
    Uvnitř closure, který předávám v metodě edit(), se zpracování nezastaví, i když tam hodím breakpoint.
  4. při testování controlleru lze přidat parametry do requestu podobně jako je to při skutečném provozu. V dokumentaci je popsán tento způsob:
    def controller = new AuthenticationController()
    controller.params.login = "marcpalmer"
    controller.params.password = "secret"
    controller.params.passwordConfirm = "secret"
    controller.signup()
    To však lze provést i pomocí Map parametru.
    def controller = new AuthenticationController()
    controller.request.parameters = [login: "marcpalmer", password: "secret", passwordConfirm: "secret"]
    controller.signup()

  5. Odlišný počet parametrů při použití controller.request.parameters a  controller.params. Mám-li jako parametr něco takového:
    [

    "visitListSize": 1.toString(), "visitList[0].date_day": 1.toString(), "visitList[0].date_month": 1.toString(),


    "visitList[0].date": Date.parse("dd-MM-yyyy", "01-01-2012").toString(), "visitList[0].date_year": 2012.toString()

    ]
    a použiji controller.request.parameters jako pro přiřazení parametrů do controlleru, v controlleru pak mám o 1 parametr víc. Tím je mapa vytvořená z visitList[0], což je stejné chování jako controller za běžného provozu. Použiji-li však pro přiřazení parametrů konstrukci controller.params jako v manuálu, tak mapa chybí.

Žádné komentáře:

Okomentovat