单元测试:如何覆盖一个实现了Runnable或Callable的内部类
背景
假如有这样一个类:
@Component
public class TaskExecutorService {
// 内部类实现Callable接口
public static class StringCallableExample implements Callable<String> {
@Autowired
private SomeService someService;
@Override
public String call() throws Exception {
someService.performAction();
return "success";
}
}
}
@Component
class SomeService {
public String performAction() {
// 执行一些业务逻辑
return "Service Action Performed";
}
}
需要单测覆盖验证其中内部类的 call()
方法,直接使用 @Mock
模拟注入内部类中的组件,会出现空指针异常!
解决方案
为了测试这个实现 Callable
的内部类,我们可以创建该内部类的实例,并通过调用它的 call()
方法来执行单元测试。
首先:我们需要模拟SomeService
,然后注入到TaskExecutorService.StringCallableExample
的实例中。
其次:为了注入模拟的服务,需要使用反射获取StringCallableExample
内部类中名为someService
的字段,并设置它为可访问,然后将模拟的SomeService
实例注入到这个字段中。因为内部类中 @Autowired
注解注入的组件直接使用 @Mock
会出现空指针异常,因为模拟注入不成功。
以下是如何覆盖 TaskExecutorService.StringCallableExample
的单元测试,流程示例:
- 创建
SomeService
的模拟实例。 - 创建
TaskExecutorService.StringCallableExample
的实例。 - 使用反射技术将模拟的
SomeService
注入到StringCallableExample
实例中。(此示例中使用的injectMockInnerClassService
方法) - 调用
StringCallableExample
的call()
方法并验证期望的行为。
代码示例:
这是实现单元测试的代码示例:
@RunWith(MockitoJUnitRunner.Silent.class)
public class TaskExecutorServiceTest {
@InjectMocks
private TaskExecutorService taskExecutorService;
@Mock
private SomeService mockSomeService;
@Before
public void setUp() throws Exception {
}
/**
* 内部类的组件注入
*/
private void injectMockInnerClassService(TaskExecutorService.StringCallableExample innerClass) {
try {
// 使用反射将mockSomeService注入到StringCallable实例中
java.lang.reflect.Field someServiceField = innerClass.getClass().getDeclaredField("someService");
someServiceField.setAccessible(true);
someServiceField.set(innerClass, mockSomeService);
} catch (Exception e) {
throw new RuntimeException("注入模拟对象失败", e);
}
}
@Test
public void testTaskExecutorService() throws Exception {
TaskExecutorService.StringCallableExample stringCallableInnerClass = new TaskExecutorService.StringCallableExample();
// 利用反射技术注入内部类使用的组件,避免注入失败引起的空指针异常
injectMockInnerClassService(stringCallableInnerClass);
// 安排
when(mockSomeService.performAction()).thenReturn("Service Action Performed");
// 动作
String result = stringCallableInnerClass.call();
// 断言
assertEquals("success", result);
// 验证
verify(mockSomeService).performAction();
}
}
标题:单元测试:如何覆盖一个实现了Runnable或Callable的内部类
作者:mmzsblog
地址:https://www.mmzsblog.cn/articles/2023/12/25/1703488352038.html
如未加特殊说明,文章均为原创,转载必须注明出处。均采用CC BY-SA 4.0 协议!
本网站发布的内容(图片、视频和文字)以原创、转载和分享网络内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。若本站转载文章遗漏了原文链接,请及时告知,我们将做删除处理!文章观点不代表本网站立场,如需处理请联系首页客服。• 网站转载须在文章起始位置标注作者及原文连接,否则保留追究法律责任的权利。
• 公众号转载请联系网站首页的微信号申请白名单!
