Pembaruan JSF mengelola kacang dengan pendengar ServletContext untuk pengujian

Dalam aplikasi JSF 2.2, saya ingin membuat file perang untuk pengujian dengan Selenium. Di webtest.war itu, saya ingin mengganti kelas pusat, yang disebut NodeCache, dengan versi tiruan, yang disebut WebtestNodeCache, untuk menjaga database dan dependensi eksternal lainnya tidak ikut diuji.

NodeCache adalah kacang yang dikelola:

@javax.faces.bean.ManagedBean(name = NodeCache.INSTANCE)
@javax.faces.bean.ApplicationScoped
public class NodeCache {
    public static final String INSTANE = "nodecache";
    // ...
}

Untuk menyelinap di WebtestNodeCache, saya menggunakan ServletContextListener seperti ini:

public class WebtestContextListener implements ServletContextListener {
     @Override
     public void contextInitialized(ServletContextEvent event) {
         WebtestNodeCache nodeCache = new WebtestNodeCache();
         ServletContext context = event.getServletContext();
         context.setAttribute(NodeCache.INSTANCE, nodeCache);
     }

     @Override
     public void contextDestroyed(ServletContextEvent sce) {}
}

Dalam build normal, WebtestContextListener dan WebtestNodeCache dikecualikan dari file perang, dalam build pengujian, keduanya disertakan.

Tampaknya ini berhasil: ketika saya masuk, saya mendapatkan node tiruan dari WebtestNodeCache.

Apakah ini cara yang dapat diandalkan untuk mengganti kacang dalam konteks aplikasi atau apakah saya hanya beruntung?

Apakah ada cara yang lebih baik untuk menyelinap ke dalam boneka uji?


person Robert    schedule 12.05.2017    source sumber


Jawaban (1)


Menggunakan anotasi @ManagedBean dan Listener untuk mengganti objek tidak berhasil. Kode tersebut selalu menggunakan kacang terkelola kode produksi yang tidak di-mock.

Mendefinisikan @ManagedBean baru dengan nama yang sama merupakan kesalahan dan mencegah penerapan.

Saya berakhir dengan ini:

  • Letakkan anotasi @ManagedBean dengan nama yang sama pada kacang asli dan tiruannya.

  • Saat membuat, hanya sertakan tiruan saat membuat webtest.war, tetapi jangan di build biasa.

  • Saat membuat, minta skrip build (Gradle dalam kasus saya) menyalin dan memfilter sumbernya, mencari komentar khusus di belakang deklarasi @ManagedBean dalam kode produksi dan mengambil baris ini untuk menghapus deklarasi @ManagedBean pada kode produksi sehingga hanya yang ada di tiruan tetap ada.

Jadi NodeCache asli terlihat seperti ini sekarang:

@javax.faces.bean.ManagedBean(name = NodeCache.INSTANCE) // webtest:remove
@javax.faces.bean.ApplicationScoped // webtest:remove
public class NodeCache {
    public static final String INSTANE = "nodecache";
    // ...
}

dan versi tiruannya memiliki anotasi yang sama, hanya saja tanpa komentar:

@javax.faces.bean.ManagedBean(name = NodeCache.INSTANCE)
@javax.faces.bean.ApplicationScoped
public class WebtestNodeCache extends NodeCache {
    // ...
}

Berikut adalah bagian yang relevan dari skrip build Gradle:

boolean isWebtest = false
gradle.taskGraph.whenReady { taskGraph ->
    isWebtest = taskGraph.hasTask(compileWebtestWarJava);
}

task copySrc(type: Copy) {
    from "src"
    into "${buildDir}/src"
    outputs.upToDateWhen {
        // Always execute this task so that resources do or don't get filtered
        // when switching between normal war file and webtests.
        false
    }
    filter { String line ->
        isWebtest && line.contains("webtest:remove") ? null : line;
    }
}

Ini memecahkan masalah bagi saya. Semoga orang lain merasakan manfaatnya.

person Robert    schedule 12.06.2017