我正在使用Struts2框架,并希望对下面的execute
方法进行单元测试:
public String execute() {
setDao((MyDAO) ApplicationInitializer.getApplicationContext().getBean("MyDAO"));
setUserPrincipal(); //fetches attribute from request and stores it in a var
setGroupValue(); //
setResults(getMyDao().getReportResults(getActionValue(), getTabName());
setFirstResultSet((List) getResults()[0]);
setSecondResultSet((List) getResults()[1]);
return SUCCESS;
}
正如您所看到的,大多数逻辑都与数据库相关。那么我该如何进行单元测试呢?我想通过模拟其中包含很少请求变量的HTTPServletRequest
进行单元测试。
我的问题是:
我很欣赏任何展示如何真正实现这一目标的书/文章。
答案 0 :(得分:6)
您向我们展示的代码不足以完全回答您的问题。
setDao((MyDAO) ApplicationInitializer.getApplicationContext().getBean("MyDAO"));
这是最难的一行,因为它使用静态方法。我们需要了解ApplicationInitializer
的工作原理。在理想世界中,getApplicationContext()
方法应返回ApplicationContext
的模拟。在MyDAO
时,此模拟应返回getBean("MyDAO")
。 mockito完全有能力处理这个问题,以及所有其他模拟框架。
setUserPrincipal(); //fetches attribute from request and stores it in a var
请求来自哪里?是否注入了动作类?如果是这样,只需注入模拟的请求对象,例如MockHttpServletRequest
setGroupValue(); //
与上述相同?请提供更多详细信息,此方法实际上做了什么?
setResults(getMyDao().getReportResults(getActionValue(), getTabName());
以前创建的模拟应该在使用给定参数调用getReportResults()
时返回一些内容。
setFirstResultSet((List) getResults()[0]);
setSecondResultSet((List) getResults()[1]);
我想下面的方法在动作类上设置了一些字段。因为您可以完全控制从模拟getReportResults()
返回的内容,所以这不是问题。
return SUCCESS;
您可以断言SUCCESS
是否是执行结果。
如何伪造/模拟请求变量,就好像它来自浏览器
见上文,Spring中有一个内置的模拟。
我的单元测试应该调用实际的DAO并确保数据回来吗?
如果您的单元测试称为真正的DAO,则不再进行单元测试。这是一次集成测试。
如果是这样,我怎么能从单元测试中调用DAO,因为DAO绑定到服务器,因为jndi池设置驻留在应用服务器上。
这意味着您正在进行集成测试。在这种情况下,您应该使用内存数据库,如h2,这样您仍然可以在ci服务器上运行测试。您必须以某种方式配置您的应用程序以从不同位置获取DataSource
。
实质上,你应该向Struts动作类中注入所有内容的模拟。你可以告诉mocks在调用时返回任何值。然后,在调用execute()
之后,您可以验证调用的给定方法,字段集和结果值是否正确。考虑将其拆分为多个测试。
MyDAO
注入您的操作类。第一行已经过时了。答案 1 :(得分:1)
此代码难以进行单元测试,因为您不是按预期使用Spring(即作为依赖注入框架),而是将其用作工厂。依赖注入正好用于避免您正在进行的这种bean查找,这很难测试。应将DAO注入您的对象。这样,您可以在单元测试对象时注入模拟DAO。
此外,这个逻辑根本不与数据库相关。 DAO包含与数据库相关的逻辑。此操作使用 DAO,因此DAO是另一个单元(应在其自己的单元测试中进行测试)。因此,您应该注入一个模拟DAO来对此方法进行单元测试。
最后,这个方法不使用HttpServletRequest(至少不是直接),所以我不明白你为什么需要使用假请求。您可以模拟使用该请求的setXxx方法。
答案 2 :(得分:0)
而不是简单地模仿HTTPServletRequest
,怎么样
模拟对应用程序的实际自动目标请求
本身?查看Selenium即可让您这样做。
为了测试DAO(集成测试),您可以使用HSQLDB在内存中创建数据库,这将允许您从测试中创建/删除对象,并确保它们被持久/正确检索。 HSQLDB的优势在于您的测试运行速度比实际数据库快得多。在提交代码时,您可以针对实际数据库运行测试。通常,您可以在IDE中设置不同的运行配置以实现此目的。
让注入的daos可用于测试的最简单方法是让单元测试类扩展AbstractJUnit4SpringContextTests
。然后,您可以使用@ContextConfiguration
注释指向多个xml应用程序上下文文件,或者如果使用基于注释的配置,则将其指向您的上下文文件,其中包含<context:annotation-config />
声明。