2017-01-24 36 views
1

嘗試使用aem-mocks框架編寫一些適當的AEM集成測試。我們的目標是通過調用它的路徑來嘗試和測試一個servlet,例如:aem-mocks屬性測試servlet

E.g.一個AEM servlet

@SlingServlet(
     paths = {"/bin/utils/emailSignUp"}, 
     methods = {"POST"}, 
     selectors = {"form"} 
) 
public class EmailSignUpFormServlet extends SlingAllMethodsServlet { 

    @Reference 
    SubmissionAgent submissionAgent; 

    @Reference 
    XSSFilter xssFilter; 

    public EmailSignUpFormServlet(){ 

    } 

    public EmailSignUpFormServlet(SubmissionAgent submissionAgent, XSSFilter xssFilter) { 
     this.submissionAgent = submissionAgent; 
     this.xssFilter = xssFilter; 
    } 

    @Override 
    public void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException { 

     String email = request.getParameter("email"); 
     submissionAgent.saveForm(xssFilter.filter(email)); 

    } 
} 

這裏是相應的測試,嘗試和做集成測試。注意我是如何調用servlet的「doPost」方法的,而不是通過某些API「POST」。

public class EmailSignUpFormServletTest { 

    @Rule 
    public final AemContext context = new AemContext(); 

    @Mock 
    SubmissionAgent submissionAgent; 

    @Mock 
    XSSFilter xssFilter; 

    private EmailSignUpFormServlet emailSignUpFormServlet; 

    @Before 
    public void setup(){ 
     MockitoAnnotations.initMocks(this); 
     Map<String,String> report = new HashMap<>(); 
     report.put("statusCode","302"); 
     when(submissionAgent.saveForm(any(String.class)).thenReturn(report); 
    } 

    @Test 
    public void emailSignUpFormDoesNotRequireRecaptchaChallenge() throws IOException { 


     // Setup test email value 
     context.request().setQueryString("[email protected]"); 

     //=================================================================== 
     /* 
     * WHAT I END UP DOING: 
     */ 
     // instantiate a new class of the servlet 
     emailSignUpFormServlet = new EmailSignUpFormServlet(submissionAgent, xssFilter); 

     // call the post method (Simulate the POST call) 
     emailSignUpFormServlet.doPost(context.request(),context.response()); 

     /* 
     * WHAT I WOULD LIKE TO DO:   
     */ 
     // send request using some API that allows me to do post to the framework 
     // Example: 
     // context.request().POST("/bin/utils/emailSignUp") <--- doesn't exist! 
     //=================================================================== 

     // assert response is internally redirected, hence expected status is a 302 
     assertEquals(302,context.response().getStatus()); 
    } 

} 

我已經做了關於如何可以這樣做(here)和(here)了大量的研究,而這些鏈接顯示了很多關於如何設置爲context.request()對象的各種參數。但是,他們只是沒有說明如何最終執行'post'調用。

回答

1

你要做的是將UT與IT混合使用,所以這至少在aem-mocks框架中不會很容易。讓我解釋一下爲什麼。

假設你可以打電話給你所需的代碼

/* 
    * WHAT I WOULD LIKE TO DO:   
    */ 
    // send request using some API that allows me to do post to the framework 
    // Example: 
    // context.request().POST("/bin/utils/emailSignUp") <--- doesn't exist! 
    //=================================================================== 

您的測試將結束在執行SlingAllMethodsServlet類和它的父類所有的邏輯。我是假設,這不是你想測試,因爲這些類不是你的邏輯的一部分,他們已經有其他的UT/IT(在各自的Apache項目下)以滿足測試需求。

另外,在看你的代碼,散裝的核心邏輯在於以下剪斷

String email = request.getParameter("email"); 
submissionAgent.saveForm(xssFilter.filter(email)); 

你的UT標準由下面的行代碼中已經滿足:

emailSignUpFormServlet.doPost(context.request(),context.response()); 

,因爲它涵蓋了大部分的邏輯。

現在,如果您正在尋找合適的IT來發布參數並將它們解析爲doPost方法,那麼aem-mocks不是它的框架,因爲它沒有以簡單的方式提供它。

在理論上,您可以模擬來自資源解析器,資源提供程序和sling servlet執行程序的所有層,以將參數一直傳遞到您的核心邏輯。這可以工作,但因爲這將不利於你的事業:

  • 大部分的代碼通過其他UT
  • 太多的內部嘲諷的依賴已經測試可以讓測試片狀或版本而定。

如果你真的想要做純粹的IT,那麼在實例中託管servlet並通過HttpClient訪問它將會更容易。這將確保所有圖層都被擊中。很多測試都是通過這種方式完成的,但對於要測試的功能而言,感覺有點沉重,並且有更好的方法來完成測試。

另外,爲什麼context.request().POST不存在的原因是因爲context.request()對於測試而言是一個模擬狀態。你想要實際綁定和模擬Http。需要某種方式解析到您的servlet並且不受框架支持的Post操作。

希望這會有所幫助。