• 认真地记录技术中遇到的坑!

Java JUnit 单元测试

Java 悠悠 2年前 (2017-11-02) 954次浏览 0个评论

一个优秀的开发,不能等到程序交到测试人员手上才发现代码的问题。需要学会自己书写单元测试,保证自己代码的质量。

添加单元测试

单元测试需要引入 JUnit 相关的包,一般来说,使用IDE添加JUnit单元测试的时候,会自动添加。Maven的单元测试配置如下:

<dependency>
   <groupId>junit</groupId>
   <artifactId>junit</artifactId>
   <version>${junit.version}</version>
   <scope>test</scope>
</dependency>

Eclipse平台

如果项目没有 JUnit 依赖,则需要添加,右键项目选择: Properties -> Java Build Path Libaries -> Add Library -> Junit ->Junit 4,添加JUnit依赖,可参考下面的操作示意图,注意红框部分。

Java JUnit 单元测试

添加依赖之后,选择需要进行单元测试的类,右键选择: New -> Junit Test Case,在弹出来的单元测试向导选择 New JUnit 4 test,这儿要和Maven配置版本相同。一般选择4版本。

注意选择 Source 项,一般放在单独的测试 test 文件夹下,和 src 对应。

注意选择的 Superclass 项,选择适当的父类。下一步,选择需要进行测试的方法。

点击完成以后,就在 test 目录下生产相应的测试类了。一般为原来的类+Test结尾。

intellij IDEA平台

IDEA需要进入需要测试的类的源代码里面,把鼠标放在类名上,右键选择: goto -> test ->Create New Test,即可弹出测试类创建引导框:

Java JUnit 单元测试

在弹出的测试引导款中填入相应的项,以及选择需要进行测试的方法,点击OK即可生成测试类,IDEA会自动把生成的测试类放到 test 目录下面。

相比于Eclipse,IDEA要特别注意标记文件夹的属性,要不然后面会出各种各样的问题。标记方法如下:

选择菜单:File -> Project Structure -> Modules,在最右边的文件导向中选择相应的文件和标记,Project Structure配置在IDEA中非常重要,无论是新建一个项目还是导入一个项目,首要的事情一定是标记不同的目录的属性,告诉IDEA该怎么处理这些文件。

Java JUnit 单元测试

SpringMVC JUnit单元测试

下面针对SpringMVC类型项目单元测试进行讲解。

对SpringMVC进行单元测试时,需要执行SpringMVC启动过程,加载相关的配置文件,一般我会使用一个公有父类来做这些事情:

import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;

@RunWith(SpringJUnit4ClassRunner.class)
//@WebAppConfiguration(value = "src/main/webapp")
@ContextConfiguration(locations = {
        "file:src/main/webapp/WEB-INF/mvc-dispatcher-servlet.xml",
        "file:src/main/webapp/WEB-INF/spring/*.xml"})
public class BaseJunitTest{
}

这个父类没有任何的测试示例,只是加载了公有的配置,注意到注解 @ContextConfiguration 加载的配置,这里根据你在项目中配置文件的位置,选择使用 file: , classpath, classpath*,如果你发现出现各种问题,无法启动或者加载配置,请使用 file 。比如下面的方式,如果你进行配置的位置很奇葩,那么下面的加载项会找不到位置。

classpath:applicationContext.xml

# 如果不能找到配置文件的话,使用下面地址代替,file:后面使用你配置中 servlet.xml 的真实位置
file:src/main/webapp/WEB-INF/mvc-dispatcher-servlet.xml

对Service层和Dao层测试

对Service层和Dao层的测试,只需要在测试类中使用 Service 和 Dao 中依赖注入的资源即可测试它们的方法:

public class UserServiceTest extends BaseJunitTest{
    @Resource  // 直接注入 Service 或 Dao 即可访问方法进行测试
    private UserService userService

    @Test  // 标记这是一个测试方法
    public void getData() throws Exception {
        User user = userService.getUserById(1);
        System.out.println("user");
    }
}

对Controller层的测试

一般来说,好的系统架构 Controller 层只会进行入口参数处理,返回值封装等简单的操作,可以直接模拟请求等方式测试。

对于Controller返回页面的情况,一般测试返回状态码,cookie等信息。当然也可以使用单元测试:使用MockMvc模拟通过url的接口调用。下面是一个简单例子:

public class UserControllerTest extends BaseJunitTest{
    @Autowired
    private UserController userController;  // 注入控制器实例

    private MockMvc mockMvc;

    @Before
    public void setup(){  // 初始化URL对象
        mockMvc = MockMvcBuilders.standaloneSetup(userController).build();
    }

    @Test
    public void getTest() throws Exception {
        ResultActions resultActions = this.mockMvc.perform(MockMvcRequestBuilders.post("/show_user3").param("id", "1"));// 使用MockMvc模拟请求
        MvcResult mvcResult = resultActions.andReturn();
        String result = mvcResult.getResponse().getContentAsString();
        // 可以从response里面取状态码,header,cookies...
        // System.out.println(mvcResult.getResponse().getStatus());
    }
}

单元测试规则

单元测试应该是全自动执行的,并且非交互式的。测试框架通常是定期执行的,执行过程必须完全自动化才有意义。输出结果需要人工检查的测试不是一个好的单元测试。单元测试中不准使用 System.out 来进行人肉验证,必须使用 assert 来验证。单元测试尽量做到AIR原则和BCDE原则:

  1. A:Automatic,单元测试需要测试框架自动化执行,才有意义。
  2. I:Independent,单元测试用例之间互相独立,不存在依赖关系。
  3. R:Repeatable,单元测试可以被重复执行,且结果一致。
  4. B: Border ,边界值测试,包括循环边界、特殊取值、特殊时间点、数据顺序等。
  5. C: Correct ,正确的输入,并得到预期的结果。
  6. D: Design ,与设计文档相结合,来编写单元测试。
  7. E: Error ,强制错误信息输入(如:非法数据、异常流程、非业务允许输入等) ,并得到预期的结果。

单元测试注解和断言

JUnit提供了一些针对测试行为的注解,使用这些注解,可以染测试更加灵活。

@Before 初始化方法
@After 释放资源
@Test 测试方法,在这里可以测试期望异常(expected 参数)和超时时间(timeout 参数)
@Ignore 忽略的测试方法
@BeforeClass 针对所有测试,只执行一次,且必须为static void
@AfterClass 针对所有测试,只执行一次,且必须为static void
@RunWith 指定测试类使用某个运行器
@Parameters 指定测试类的测试数据集合
@Rule 允许灵活添加或重新定义测试类中的每个测试方法的行为
@FixMethodOrder 指定测试方法的执行顺序

另外是用于自动化测试的一些断言,应该尽量避免人工查看输出的方式进行单元测试。

assertArrayEquals(expecteds, actuals) 查看两个数组是否相等。
assertEquals(expected, actual) 查看两个对象是否相等。类似于字符串比较使用的equals()方法
assertNotEquals(first, second) 查看两个对象是否不相等。
assertNull(object) 查看对象是否为空。
assertNotNull(object) 查看对象是否不为空。
assertSame(expected, actual) 查看两个对象的引用是否相等。类似于使用“==”比较两个对象
assertNotSame(unexpected, actual) 查看两个对象的引用是否不相等。类似于使用“!=”比较两个对象
assertTrue(condition) 查看运行结果是否为true。
assertFalse(condition) 查看运行结果是否为false。
assertThat(actual, matcher) 查看实际值是否满足指定的条件
fail() 让测试失败

 


转载请注明出处 Java JUnit 单元测试
喜欢 (2)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址