7种方法检测安卓模拟器_两种不同的模拟方法

7种方法检测安卓模拟器

无论您选择采用TDD还是采用更传统的方法,都将单独测试类。 这通常意味着您使用接口进行编码,并将依赖项注入类中。

去年,我不得不测试一个servlet。 Servlet是展示容器外测试的展示柜,因为它们依赖于doXxx()方法中的所述容器。 这些方法中的每一个都依赖于HttpServletRequestHttpServletResponse 两者都是在Servlet API中没有具体实现的接口。 因此,基本上,在您的测试中,您会遇到三个选择:

  1. 使用您的容器实现(糟糕!),
  2. 创建自己的实现(相当耗时),
  3. 使用没有依赖关系的已有实现。

选择第三个选项,我发现了这个小小的珠宝MockRunner 。 MockRunner为您提供以下API和框架的模拟实现:

  • 日本国家发展研究院
  • EJB2,
  • JDBC,
  • JMS,
  • Servlet,
  • TagLib,
  • Struts

所有这些模拟实现均应按需运行。 例如,如果在测试开始时将对象放入模拟会话中,并且此后仍然处于同一请求中,则可以检查对象是否仍在此处。 让我们考虑以下servlet方法进行测试:

@Override
protectedvoiddoGet(HttpServletRequestaRequest,HttpServletResponseaResponse)throwsServletException,IOException{

    Stringaction=aRequest.getParameter("action");
    HttpSessionsession=aRequest.getSession();
    Objectobject=session.getAttribute("number");
    intnumber=object==null?0:(Integer)object;

    if("add".equals(action)){
        number++;
        session.setAttribute("number",number);

    }elseif("remove".equals(action)){
        number--;
        session.setAttribute("number",number);

    }elseif("reset".equals(action)){
        session.setAttribute("number",0);
    }
}

您如何使用MockRunner测试此代码? 第一件事是从com.mockrunner.servlet.BasicServletTestCaseAdapter继承。 代码如下:

publicclassMockRunnerTestextendsBasicServletTestCaseAdapter{

    /**
     * Setup the servlet to test.
     */
    @Override
    publicvoidsetUp()throwsException{
        super.setUp();
        createServlet(SessionServlet.class);
    }

    /**
     * Test method for
     * {@link SessionServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)}.
     *
     * @throws IOException
     * @throws ServletException
     */

    publicvoidtestDoGetAdd()throwsServletException,IOException{
        addRequestParameter("action","add");
        doGet();
        Objectobject=getSessionAttribute("number");
        assertTrue(Integer.class.isAssignableFrom(object.getClass()));
        intnumber=(Integer)object;
        assertEquals(1,number);
    }

    /**
     * Test method for
     * {@link SessionServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)}.
     *
     * @throws IOException
     * @throws ServletException
     */
    publicvoidtestDoGetRemove()throwsServletException,IOException{
        addRequestParameter("action","remove");
        doGet();
        Objectobject=getSessionAttribute("number");
        assertTrue(Integer.class.isAssignableFrom(object.getClass()));
        intnumber=(Integer)object;
        assertEquals(-1,number);
    }

    /**
     * Test method for
     * {@link SessionServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)}.
     *
     * @throws IOException
     * @throws ServletException
     */
    publicvoidtestDoGetReset()throwsServletException,IOException{
        addRequestParameter("action","reset");
        doGet();
        Objectobject=getSessionAttribute("number");
        assertTrue(Integer.class.isAssignableFrom(object.getClass()));
        intnumber=(Integer)object;
        assertEquals(0,number);
    }
}

像这样测试我们的servlet很好,尽管使用MockRunner有一些限制:

  • 您必须继承MockRunner的基类,
  • 因此,您将不得不使用JUnit v3。 您也不能使用TestNG或JUnit v4,
  • 开箱即用的测试功能有限。 如果出于某种原因,您决定创建一个具有其他功能的超级servlet,则必须扩展MockRunner框架。 同样,如果出现新的API,则必须创建自己的适配器,
  • 您必须记住在setUp()方法中调用super.setUp() (确实不是一个好主意),
  • 最后但并非最不重要的一点是,自08年夏季以来,MockRunner项目一直没有任何活动。

然后我对Mockito产生了兴趣。 Mockito是一个“真正的” Mock框架,可增强您的接口,并使用CGLIB进行分类以提供方法的存根:即,您提供了链接到方法调用的代码。 如今,Mockito似乎非常炒作,但趋势仍在流行。 以下代码向您展示了使用Mockito制作的测试类:

publicclassMockitoTest{

    /** Servlet under test. */
    privateSessionServletservlet;

    /** Mock request. */
    privateHttpServletRequestrequest;

    /** Mock response. */
    privateHttpServletResponseresponse;

    /** Mock session. */
    privateHttpSessionsession;

    /** Session's attribute map. */
    privateMapattributes;

    /** Request's parameter map. */
    privateMapparameters;

    /**
     * Launches Mockito configuration from annotations.
     */
    @Before
    publicvoidsetUp(){

        attributes=newHashMap();
        parameters=newHashMap();
        servlet=newSessionServlet();
        request=mock(HttpServletRequest.class);
        response=mock(HttpServletResponse.class);
        session=mock(HttpSession.class);

        when(request.getSession()).thenReturn(session);
        when(request.getParameterMap()).thenReturn(parameters);
        when(request.getParameter(anyString())).thenAnswer(newAnswer(){
            /**
             * @see org.mockito.stubbing.Answer#answer(org.mockito.invocation.InvocationOnMock)
             */
            @Override
            publicObjectanswer(InvocationOnMockaInvocation)throwsThrowable{
                Stringkey=(String)aInvocation.getArguments()[0];
                returnparameters.get(key);
            }
        });

        when(session.getAttribute(anyString())).thenAnswer(newAnswer(){
            /**
             * @see org.mockito.stubbing.Answer#answer(org.mockito.invocation.InvocationOnMock)
             */
            @Override
            publicObjectanswer(InvocationOnMockaInvocation)throwsThrowable{
                Stringkey=(String)aInvocation.getArguments()[0];
                returnattributes.get(key);
            }
        });
        Mockito.doAnswer(newAnswer(){
            /**
             * @see org.mockito.stubbing.Answer#answer(org.mockito.invocation.InvocationOnMock)
             */
            @Override
            publicObjectanswer(InvocationOnMockaInvocation)throwsThrowable{
                Stringkey=(String)aInvocation.getArguments()[0];
                Objectvalue=aInvocation.getArguments()[1];
                attributes.put(key,value);
                returnnull;
            }
        }).when(session).setAttribute(anyString(),anyObject());
    }

    /**
     * Test method for
     * {@link SessionServlet#doGet(HttpServletRequest, HttpServletResponse)} .
     *
     * @throws IOException
     * @throws ServletException
     */
    @Test
    publicvoidtestDoGetAdd()throwsServletException,IOException{
        parameters.put("action","add");
        servlet.doGet(request,response);
        Objectobject=attributes.get("number");
        assertNotNull(object);
        assertTrue(Integer.class.isAssignableFrom(object.getClass()));
        intnumber=(Integer)object;
        assertEquals(1,number);
    }

    /**
     * Test method for
     * {@link SessionServlet#doGet(HttpServletRequest, HttpServletResponse)} .
     *
     * @throws IOException
     * @throws ServletException
     */
    @Test
    publicvoidtestDoGetRemove()throwsServletException,IOException{
        parameters.put("action","remove");
        servlet.doGet(request,response);
        Objectobject=attributes.get("number");
        assertNotNull(object);
        assertTrue(Integer.class.isAssignableFrom(object.getClass()));
        intnumber=(Integer)object;
        assertEquals(-1,number);
    }

    /**
     * Test method for
     * {@link SessionServlet#doGet(HttpServletRequest, HttpServletResponse)} .
     *
     * @throws IOException
     * @throws ServletException
     */
    @Test
    publicvoidtestDoGetReset()throwsServletException,IOException{
        parameters.put("action","reset");
        servlet.doGet(request,response);
        Objectobject=attributes.get("number");
        assertNotNull(object);
        assertTrue(Integer.class.isAssignableFrom(object.getClass()));
        intnumber=(Integer)object;
        assertEquals(0,number);
    }
}

Mockito严重缺乏针对新手的文档。 尽管Mockito类有充分的文献资料,但我认为应该对哲学和体系结构进行外部介绍。 不过,这是我可以解决的许多Google Code项目的限制。

恕我直言,MockRunner与API集成程度更高,隐藏了实现细节,而对于Mockito,您需要了解实现以提供足够的存根。 Mockito的测试类的代码大小约为MockRunner的两倍。 因此,尽管会迫使我使用旧版本的JUnit,并在没有此类约束的情况下使用Mockito,但我将继续使用MockRunner来使用其集成API的类。

总之,我承认这两种测试工具都具有截然不同的方法和范围。 我仍然觉得Mockito的使用有点复杂。

使自己的想法:

  • 模拟赛跑者
  • 莫基托

翻译自: https://blog.frankel.ch/two-different-mocking-approaches/

7种方法检测安卓模拟器

你可能感兴趣的:(7种方法检测安卓模拟器_两种不同的模拟方法)