1、单元测试是什么?步骤
单元测试(Unit Testing)是软件开发中的一种测试方法,用于确保单个代码单元(如函数或方法)按照预期运行。通过编写单元测试,开发人员可以检查每个代码单元是否能够独立地产生正确的结果。单元测试有助于识别和修复代码中的错误,从而提高软件质量。
通常,一个单元测试的步骤如下:
- 编写测试用例:针对代码单元编写一组测试用例,每个测试用例包含特定的输入和预期输出。
- 运行测试:使用测试框架运行编写的单元测试,测试框架通常可以自动执行所有测试用例并报告结果。
- 检查结果:测试框架会报告每个测试用例的通过或失败状态。如果某个测试用例失败了,这意味着代码单元存在问题,需要进行调试和修复。
- 修复代码:针对失败的测试用例,开发人员需要调查错误原因,并修改相应的代码,以使测试通过。
- 重复运行测试:在修复代码后,再次运行所有测试用例,确保修复后的代码没有引入新的错误。
- 单元测试的主要目的是确保代码的可靠性、稳定性和可维护性。通过编写和执行单元测试,开发人员可以在项目的早期阶段发现和修复错误,从而避免了在项目后期出现难以排查的问题。
2、简单的单元操作,Demo
Spring Boot中实现单元测试,步骤如下:
- 添加依赖:
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
- 编写测试类:创建一个要测试的类相对应的测试类。测试类应位于与要测试的类相同的包中,并遵循命名约定,例如
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 {
// 编写测试用例
}
- 编写测试用例:在测试类中,为要测试的每个方法编写一个或多个测试用例。使用JUnit的
@Test
注解来标记测试方法。可以使用断言(如assertEquals
、assertTrue
等)来验证方法的输出是否符合预期。
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);
}
}
- 运行测试,如果有测试用例失败,就修改对应的实现代码,并重新运行测试,直到所有测试用例均通过。
再补充一个例子:
例如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)是一种测试技术,用于在测试过程中替换实际组件(如方法、对象或服务)的行为。打桩通常用于模拟代码中的某些部分,以便在测试中控制它们的行为。这样就可以专注于测试目标方法或类,而无需担心外部依赖或其他组件的影响。
打桩的主要优点是:
- 隔离:通过使用
打桩
隔离要测试的代码单元,使其不受外部依赖或其他组件的干扰。这样可以确保单元测试只关注目标代码的功能,而不是整个系统的行为。 - 可控:打桩允许预先定义替换组件的行为。这意味着可以在测试中精确地控制这些组件的输出,从而更容易地测试不同的场景和边界条件。
- 简化:有时,实际组件可能很复杂或难以设置。通过使用打桩,可以替换这些组件为简单的、易于管理的模拟对象,从而简化测试过程。
要在单元测试中实现打桩,可以使用一些模拟框架,比如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);
}
}
在这个示例中,我们使用Mockito
为DependencyClass
创建了一个模拟对象,并为其someMethod
方法设置了预期行为。然后,我们将模拟对象传递给 YourClass
,并执行测试。
通过这种方式,我们可以确保测试仅关注 YourClass
的行为,而不受DependencyClass
的实际实现的影响。
如有错误,还请多多指教!
转载或者引用本文内容请注明来源及原作者:橘足轻重;