aem-mocks属性测试一个servlet

时间:2017-01-24 16:54:34

标签: unit-testing osgi aem

尝试使用aem-mocks框架编写一些正确的AEM集成测试。目标是通过调用其路径来尝试测试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=test.only@mail.com");

        //===================================================================
        /*
         * 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),这些链接显示了很多关于如何为上下文设置各种参数的信息.request()对象。但是,他们只是没有说明如何最终执行“帖子”。调用

1 个答案:

答案 0 :(得分: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就不是它的框架,因为它不能以简单的方式提供它。

理论上,您可以模拟资源解析器,资源提供程序和吊索servlet执行程序中的所有层,以将参数一直传递给核心逻辑。这可以工作,但它不会有益于你的事业,因为:

  • 大多数代码已经通过其他UT
  • 进行了测试
  • 太多的内部模拟依赖项可能会使测试变得不稳定或依赖于版本。

如果你真的想做纯IT,那么在一个实例中托管servlet并通过HttpClient访问它会更容易。这将确保所有图层都被击中。很多测试都是通过这种方式完成的,但是对于您想要测试的功能感觉有点沉重,并且有更好的方法。

另外context.request().POST不存在的原因是因为context.request() for是为了测试而被模拟的状态。您希望实际绑定和模拟Http.Post操作,这些操作需要某种方法来解析您的servlet,并且框架不支持。

希望这有帮助。