Java单元测试是什么?

Posted 橘足轻重

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java单元测试是什么?相关的知识,希望对你有一定的参考价值。

单元测试

1、单元测试是什么?步骤

单元测试(Unit Testing)是软件开发中的一种测试方法,用于确保单个代码单元(如函数或方法)按照预期运行。通过编写单元测试,开发人员可以检查每个代码单元是否能够独立地产生正确的结果。单元测试有助于识别和修复代码中的错误,从而提高软件质量。
通常,一个单元测试的步骤如下:

  1. 编写测试用例:针对代码单元编写一组测试用例,每个测试用例包含特定的输入和预期输出。
  2. 运行测试:使用测试框架运行编写的单元测试,测试框架通常可以自动执行所有测试用例并报告结果。
  3. 检查结果:测试框架会报告每个测试用例的通过或失败状态。如果某个测试用例失败了,这意味着代码单元存在问题,需要进行调试和修复。
  4. 修复代码:针对失败的测试用例,开发人员需要调查错误原因,并修改相应的代码,以使测试通过。
  5. 重复运行测试:在修复代码后,再次运行所有测试用例,确保修复后的代码没有引入新的错误。
  6. 单元测试的主要目的是确保代码的可靠性、稳定性和可维护性。通过编写和执行单元测试,开发人员可以在项目的早期阶段发现和修复错误,从而避免了在项目后期出现难以排查的问题。

2、简单的单元操作,Demo

Spring Boot中实现单元测试,步骤如下:

  1. 添加依赖:
    pom.xml
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
  1. 编写测试类:创建一个要测试的类相对应的测试类。测试类应位于与要测试的类相同的包中,并遵循命名约定,例如YourClassTest。在测试类中,使用@RunWith(SpringRunner.class) 注解来指定测试运行器,并使用 @SpringBootTest注解来启用Spring Boot测试功能。
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class YourClassTest 
    // 编写测试用例

  1. 编写测试用例:在测试类中,为要测试的每个方法编写一个或多个测试用例。使用JUnit的@Test注解来标记测试方法。可以使用断言(如assertEqualsassertTrue等)来验证方法的输出是否符合预期。
import org.junit.Test;
import static org.junit.Assert.assertEquals;

public class YourClassTest 
    @Test
    public void testYourMethod() 
        YourClass yourClass = new YourClass();
        int expectedResult = 42;
        int actualResult = yourClass.yourMethod();
        assertEquals(expectedResult, actualResult);
    

  1. 运行测试,如果有测试用例失败,就修改对应的实现代码,并重新运行测试,直到所有测试用例均通过。

再补充一个例子:
例如HelloController,测试 /hello,编写测试类:

@RunWith(SpringRunner.class)
@WebMvcTest(HelloController.class)
public class HelloControllerTest 
    @Autowired
    private MockMvc mockMvc;
    @Autowired
    private ServletContext servletContext;

    @Test
    public void test1() throws Exception
        MvcResult end = mockMvc.perform(requestBuilder("/hello"))
                .andExpect(mvcResult -> 
                    if (mvcResult.getResponse().getStatus() != 200) 
                        throw new RuntimeException("failed.");
                    
                )
                .andExpect(result -> 
                    if (!result.getResponse().getContentType().contains("json")) 
                        throw new RuntimeException("failed");
                    
                ).andReturn();

        System.out.println(end);
    

    private RequestBuilder requestBuilder(String uri) 
        return MockMvcRequestBuilders.get(URI.create(uri)).accept(MediaType.APPLICATION_JSON_UTF8)
                .characterEncoding("UTF-8");
    


补充:实际项目你可能会遇到一些耦合性很强的业务方法,这个时候你就痛苦了。比如:输入参数过多,参数存在较多的等价类,这些都是设计时就要避免的。
解决办法:
1.使用全局变量/对象属性进行输出, 尽量减少函数的相互调用。
2.分离模块的I/O操作,减少函数调用。
3.对函数调用进行封装,测试时不进行调用,而是通过全局变量输出函数ID和参数。
4.对通过函数调用获取输入的情况,同样封装为函数ID和全局变量的输入。

3、什么是打桩

单元测试中的打桩(Stubbing)是一种测试技术,用于在测试过程中替换实际组件(如方法、对象或服务)的行为。打桩通常用于模拟代码中的某些部分,以便在测试中控制它们的行为。这样就可以专注于测试目标方法或类,而无需担心外部依赖或其他组件的影响。

打桩的主要优点是:

  1. 隔离:通过使用打桩隔离要测试的代码单元,使其不受外部依赖或其他组件的干扰。这样可以确保单元测试只关注目标代码的功能,而不是整个系统的行为。
  2. 可控:打桩允许预先定义替换组件的行为。这意味着可以在测试中精确地控制这些组件的输出,从而更容易地测试不同的场景和边界条件。
  3. 简化:有时,实际组件可能很复杂或难以设置。通过使用打桩,可以替换这些组件为简单的、易于管理的模拟对象,从而简化测试过程。

要在单元测试中实现打桩,可以使用一些模拟框架,比如Mockito等。
以下是一个使用Mockito进行打桩的简单示例:

import org.junit.Test;
import org.mockito.Mockito;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.when;

public class YourClassTest 
    @Test
    public void testYourMethodWithStub() 
        // 创建一个依赖类的模拟对象
        DependencyClass mockDependency = Mockito.mock(DependencyClass.class);

        // 为模拟对象的某个方法设置预期行为(打桩)
        when(mockDependency.someMethod()).thenReturn("stubbedValue");

        // 将模拟对象传递给要测试的类
        YourClass yourClass = new YourClass(mockDependency);

        // 调用要测试的方法
        String expectedResult = "expectedResult";
        String actualResult = yourClass.yourMethod();

        // 验证结果
        assertEquals(expectedResult, actualResult);
    

在这个示例中,我们使用MockitoDependencyClass创建了一个模拟对象,并为其someMethod方法设置了预期行为。然后,我们将模拟对象传递给 YourClass,并执行测试。
通过这种方式,我们可以确保测试仅关注 YourClass的行为,而不受DependencyClass的实际实现的影响。

如有错误,还请多多指教!
转载或者引用本文内容请注明来源及原作者:橘足轻重;

读《单元测试之道Java版》

       读完这本单元测试之道,我们首先要知道什么是单元测试?为什么要使用单元测试?如何进行单元测试这些都是我们需要思考的。

      单元测试是开发者编写的一小段代码,用于检验被测代码的一个很小很明确的功能是否正确。单元测试不但会使我们的工作完成的更轻松,而且会令我们的设计变得更好,甚至大大减少我们花在调试上的时间。单元测试首先要考虑的是在编写这些测试方法之前,如何测试这些可疑的方法:接着我们需要运行测试本身忙活着运行系统模块的所有其他测试,甚至如果测试运行的比较快我们可以运行整个系统的测试,及时再次测试过程中,我们需要确认每个测试是否通过,但是我们会因此养成一个习惯,快速看出代码到底是否正确的习惯。

【1】为了提高我们的测试技巧,我们主要将之测试的地方分为6点:

1.结果是否正确?

2.是否所有边界条件都正确?

3.检查反向关联

4.运用其他手段交叉检查结果

5.是否可以强制错误条件发生

6.是否满足性能要求

【2】好的测试所具有的品质

自动化  --------  调用测试自动化和检查结果自动化

彻底的  --------  测试所有可能出现的情况

可重复  --------  任意顺序的执行其中任意一个测试,产生的结果都是相同

独立的  --------  测试之间必须独立,且必须独立与周围不可控的环境

专业的  --------  代码一定是值得测试的

 

以上就是我在读完《单元测试之道Java版》的读书心得,我认为我自己对有些知识点的理解还不够透彻,有些地方我还需要更深层的理解。

以上是关于Java单元测试是什么?的主要内容,如果未能解决你的问题,请参考以下文章

Java之单元测试工具(Junit)

Java单元测试是什么?

Java单元测试介绍

Selenium 中的 JUnit 注解

读《单元测试之道Java版》

原!关于java 单元测试的一些总结