Mockito implemetation for formhandlers in ATG



我是Mockito这个概念的新手。您能否帮助我了解在 ATG 中将Mockito用于表单处理程序。一些例子将不胜感激。

对于其他类似的问题,有一个很好的答案(与ATG有关):使用-mockito-for-writing-atg-test-case。请查看它是否包含您需要的内容。

众所周知,许多特定于ATG的组件(特别是表单处理程序)"不太可测试"(与使用TDD/BDD方法开发的组件相比),OOTB组件(包括参考应用程序)的b/c设计并不总是遵循具有"低耦合和高内聚"的原则

但通用方法仍然适用于为所有 ATG 组件编写单元测试。

下面是我们用来用Mockito测试ATG FormHandlers的框架。显然,您需要输入所有适当的测试部分,但这应该可以让您开始。

    public class AcmeFormHandlerTest {
        @Spy @InjectMocks private AcmeFormHandler testObj;
        @Mock private Validator<AcmeInterface> acmeValidatorMock;
        @Mock private DynamoHttpServletRequest requestMock;
        @Mock private DynamoHttpServletResponse responseMock;
        private static final String ERROR1_KEY = "error1";
        private static final String ERROR1_VALUE = "error1value";
        @BeforeMethod(groups = { "unit" })
        public void setUp() throws Exception {
            testObj = new AcmeFormHandler();
            initMocks(this);
        }
        //Test the happy path scenario
        @Test(groups = { "unit" })
        public void testWithValidData() throws Exception {
            testObj.handleUpdate(requestMock, responseMock);
            //Assume your formhandler calls a helper method, then ensure the helper method is called once. You verify the working of your helper method as you would do any Unit test
            Mockito.verify(testObj).update(Matchers.refEq(requestMock), Matchers.refEq(responseMock), Mockito.anyString(), (AcmeBean) Mockito.anyObject());
        }
        //Test a validation exception
        @Test(groups = { "unit" })
        public void testWithInvalidData() throws Exception {
            Map<String, String> validationMessages = new HashMap<String, String>();
            validationMessages.put(ERROR1_KEY, ERROR1_VALUE);
            when(acmeValidatorMock.validate((AcmeInterface) Mockito.any())).thenReturn(validationMessages);
            testObj.handleUpdate(requestMock, responseMock);
            assertEquals(1, testObj.getFormExceptions().size());
            DropletFormException exception = (DropletFormException) testObj.getFormExceptions().get(0);
            Assert.assertEquals(exception.getMessage(), ERROR1_VALUE);
        }
        //Test a runtime exception
        @Test(groups = { "unit" })
        public void testWithRunProcessException() throws Exception {
            doThrow(new RunProcessException("")).when(testObj).update(Matchers.refEq(requestMock), Matchers.refEq(responseMock), Mockito.anyString(), (AcmeBean) Mockito.anyObject());
            testObj.handleAddGiftCardToCart(requestMock, responseMock);
            assertEquals(1, testObj.getFormExceptions().size());
            DropletFormException exception = (DropletFormException) testObj.getFormExceptions().get(0);
            Assert.assertEquals(exception.getMessage(), GENERAL_ERROR_KEY);
        }
    }

显然,以上只是一个框架,非常适合我们开发FormHandlers的方式。如果您选择,您还可以为重定向和类似的东西添加验证:

Mockito.verify(responseMock, Mockito.times(1)).sendLocalRedirect(SUCCESS_URL, requestMock);

最终,测试其他人代码的警告仍然适用。

这是我对

表单处理程序进行单元测试时所做的(至少在我设法发布 AtgDust 的主要更新之前)。请注意,我不使用通配符导入,因此我不确定这是否会导致任何命名空间冲突。

import static org.mockito.Mockito.*;
import static org.mockito.MockitoAnnotations.initMocks;
import org.junit.*;
import static org.junit.Assert.assertThat;
import static org.hamcrest.CoreMatchers.*;
import atg.servlet.*;
import some.form.handler.FormHandler;
@RunWith(JUnit4.class)
public class FormHandlerTest {
  @Mock DynamoHttpServletRequest request;
  @Mock DynamoHttpServletResponse response;
  FormHandler handler;
  @Before
  public void setup() {
    initMocks(this);
    handler = new FormHandler();
  }
  @Test
  public void testSubmitHandlerRedirects() {
    handler.handleSubmit(request, response);
    verify(response).sendLocalRedirect(eq("/success.jsp"), eq(request));
    assertThat(handler.getFormError(), is(false));
  }
}

基本思想是在模拟对象方法调用中使用 when() 为 mock/stub 设置自定义行为,以返回一些测试值或抛出异常,然后验证 () 模拟对象被调用了确切的次数(在默认情况下,一次),并对表单处理程序中已更改的数据执行任何断言。本质上,您需要使用 when() 来模拟需要返回其他模拟对象的任何类型的方法调用。什么时候需要这样做?最简单的判断方法是,当您因使用空值、零、空字符串等而获得 NPE 或其他运行时异常时。

理想情况下,在集成测试中,您将能够使用一种介于两者之间的模拟/测试 servlet,它假装像执行最小请求/会话/全局范围管理的完整应用程序服务器一样工作。据我所知,这对Arquillian来说是一个很好的用途,但我还没有开始尝试。

最新更新