【问题标题】:Using Mockito for writing ATG test case使用 Mockito 编写 ATG 测试用例
【发布时间】:2013-07-05 14:44:47
【问题描述】:

有人知道使用 Mockito 为 ATG 编写单元测试用例吗?我在护目镜时遇到了以下讨论- Automated unit tests for ATG developmentUsing PowerMock to obtain the ATG Nucleus in testing results in NPE

但需要帮助设置 Nucleus 和其他依赖项(DAS、DPS、DSS 等)以及使用 Mockito 的液滴示例测试类。

我们正在使用 ATG Dust,我们必须设置所有依赖项。我想知道我们是否可以用 Mockito 完全替换 ATG Dust。这是我们如何编写测试用例的示例 -

  1. 用于设置 Nucleus 的基类 -
package com.ebiz.market.support;

import java.io.File;
import java.util.Arrays;
import atg.nucleus.NucleusTestUtils;
import atg.test.AtgDustCase;
import atg.test.util.FileUtil;

public class BaseTestCase extends AtgDustCase {
public atg.nucleus.Nucleus mNucleus = null;
private final String ATGHOME="C://ATG/ATG9.4//home";
private final String ATGHOMEPROPERTY = "atg.dynamo.home";

protected void setUp() throws Exception {
super.setUp();
String dynamoHome = System.getProperty(ATGHOMEPROPERTY);
if(dynamoHome == null)
System.setProperty(ATGHOMEPROPERTY, ATGHOME);
File configpath = NucleusTestUtils.getConfigpath(this.getClass(), this.getClass().getName(), true);
FileUtil.copyDirectory("src/test/resources/config/test/", configpath.getAbsolutePath(), Arrays.asList(new String [] {".svn"}));
copyConfigurationFiles(new String[]{"config"}, configpath.getAbsolutePath(), ".svn");
}

public File getConfigPath() {
  return NucleusTestUtils.getConfigpath(this.getClass(), this.getClass().getName(), true);
}
}
  1. 通过扩展基类编写测试用例 -
public class BizDropletTest extends BaseTestCase {
private BizDroplet bizDroplet;

@Before
public void setUp() throws Exception {
super.setUp();
mNucleus = NucleusTestUtils.startNucleusWithModules(new String[] { "DSS", "DPS", "DAFEAR" }, this.getClass(),
this.getClass().getName(), "com/ebiz/market/support/droplet/BizDroplet");
autoSuggestDroplet = (AutoSuggestDroplet) mNucleus.resolveName("com/ebiz/market/support/droplet/BizDroplet");
try {
bizDroplet.doStartService();
} catch (ServiceException e) {
fail(e.getMessage());
}
}

/**
Other methods
*/
}

那么,Mockito 如何处理这些问题?同样,对我来说,目标是完全用 Mockito 替换 ATG Dust,因为 ATG Dust 需要大量时间来运行测试,因为依赖关系很大。

谢谢。

【问题讨论】:

    标签: mockito atg


    【解决方案1】:

    使用 Mockito,您无需设置 Nucleus 或其他依赖项(除非您需要它)。您只需模拟您需要使用的对象。

    考虑一个简单的类ProductUrlDroplet,它从存储库中检索产品,然后基于此输出一个url。 service 方法看起来像这样:

    public void service(DynamoHttpServletRequest pRequest, DynamoHttpServletResponse pResponse) throws ServletException, IOException {
        Object product = pRequest.getObjectParameter(PRODUCT_ID);
    
        RepositoryItem productItem = (RepositoryItem) product;
        String generatedUrl = generateProductUrl(pRequest, productItem.getRepositoryId());
    
        pRequest.setParameter(PRODUCT_URL_ID, generatedUrl);
        pRequest.serviceParameter(OPARAM_OUTPUT, pRequest, pResponse);
    }
    
    private String generateProductUrl(DynamoHttpServletRequest request, String productId) {
    
        HttpServletRequest originatingRequest = (HttpServletRequest) request.resolveName("/OriginatingRequest");
        String contextroot = originatingRequest.getContextPath();
    
        return contextroot + "/browse/product.jsp?productId=" + productId;
    }
    

    一个简单的测试类将是:

    public class ProductUrlDropletTest {
    
    @InjectMocks private ProductUrlDroplet testObj;
    @Mock private DynamoHttpServletRequest requestMock;
    @Mock private DynamoHttpServletResponse responseMock;
    @Mock private RepositoryItem productRepositoryItemMock;
    
    @BeforeMethod(groups = { "unit" })
    public void setup() throws Exception {
    
        testObj = new ProductUrlDroplet();
        MockitoAnnotations.initMocks(this);
        Mockito.when(productRepositoryItemMock.getRepositoryId()).thenReturn("50302372");
    }
    
    @Test(groups = { "unit" })
    public void testProductURL() throws Exception {
        Mockito.when(requestMock.getObjectParameter(ProductUrlDroplet.PRODUCT_ID)).thenReturn(productRepositoryItemMock);
    
        testObj.service(requestMock, responseMock);
        ArgumentCaptor<String> argumentProductURL = ArgumentCaptor.forClass(String.class);
        Mockito.verify(requestMock).setParameter(Matchers.eq(ProductUrlDroplet.PRODUCT_URL_ID), argumentProductURL.capture());
        Assert.assertTrue(argumentProductURL.getValue().equals("/browse/product.jsp?productId=50302372"));
    }
    
    }   
    

    关键组件是您需要初始化要测试的类 (testObj)。然后,您只需为要使用的对象的每个输入参数构造响应(在这种情况下,productRepositoryItemMock 代表RepositoryItemproductRepositoryItemMock.getRepositoryId() 返回一个String,您可以稍后对其进行测试)。

    您还会注意到,此测试仅验证 service 方法,而不是单个方法。你如何做取决于你,但通常我一直专注于在表单处理程序和液滴中测试我的servicehandleXXX 方法。

    测试 XXXManager、XXXUtil 和 XXXService 类都将有自己的测试,并且应该“模拟”到 Droplet 和表单处理程序中。不过对于这些,我会为每种方法编写测试。

    PowerMockito 只有在您需要模拟 static 方法和类时才会真正出现,并且文档足以解释这一点。

    【讨论】:

    • 谢谢。这真的对我有很大帮助。我已经编辑了这个问题。请看。
    • 关键是你不再需要'Base'类来设置Nucleus。你只嘲笑你需要的东西。因此,在上述情况下,您只需要测试BizDroplet(或者是AutoSuggestDroplet)并在那里简单地测试service 方法。如果您确实需要获取Nucleus,请记住这是一个static 呼叫,您可能需要使用PowerMockito 来代替。在 SO 上也有很多这样的例子。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-06
    • 2019-06-21
    相关资源
    最近更新 更多