文章内容前置说明:
- 框架:SpringBoot 2.4.4 , Spring Data JPA
- 使用的需求样例参考: 业务需求分析详解-如何精确识别并发问题
问题背景
假设在这样一个多模块项目中:
其依赖关系如下:
在不同的模块下通常会有一些测试代码,比如在domain模块下,有这样一段用于准备不同状态的Call实体的测试代码:
// domain的test目录下: com.peng.project.domain.entity.CallDomainPrepare
public class CallDomainPrepare {
public Call prepareCallingCall() {
// 返回一个处于Calling状态的呼叫实体
}
public void prepareBusyCall() {
// 返回一个处于Busy状态的呼叫实体
}
}
而在application模块下,有CallApplicationService,里面有一个call方法,如下所示:
@Service
@RequiredArgsConstructor
public class CallApplicationService {
private final CallDomainService callDomainService;
public Call call() {
return callDomainService.call();
}
public void cancelCall(UUID callId) {
// 执行一些前置的判断逻辑
callDomainService.cancelCall(callId);
}
}
此时如果想要测试ApplicationService的cancelCall方法,则需要先创建一个处于呼叫状态的call对象。测试方法类似于这样:
class CallApplicationServiceTest extends BaseTest {
@Autowired
private CallApplicationService callApplicationService;
@Autowired
private CallDomainService callDomainService;
@Autowired
private TestUserFactory userFactory;
@Test
@DisplayName("取消呼叫成功")
void should_cancel_call() {
Call call = callDomainService.call(
userFactory.createUser(),
userFactory.createUser(),
CallValues.builder().build());
callApplicationService.cancelCall(call.getId());
}
}
可是我们已经在domain模块的test目录下已经有了一个CallDomainPrepare类,专门用于生成各种状态的Call对象了,而在CallApplicationService的测试中却不能复用这样的类。如果后续还要继续测试 呼叫正忙、呼叫连接失败、呼叫成功等场景,依然也需要前置地生成一个呼叫中的类。有没有什么办法可以引用到在被依赖模块domain的test目录下已经定义好的一些类呢?
解决方案
在maven的插件中,有一个插件叫maven-jar-plugin,可以在我们打包的时候把test目录也打成jar包。在pom文件中增加插件配置:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
然后执行mvn verify命令,最终的打包产物有两个,一个是源代码jar,另一个则是test-jar,如图所示:
然后我们只需要在application模块中引入test模块即可,注意这里的引入有些不同:
<dependency>
<groupId>com.peng.project</groupId>
<artifactId>domain</artifactId>
<version>1.0.0</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
需要在引入的时候指定type为test-jar,这样就可以在application的test中引用到模块中的test目录定义好的类了。最终效果如下所示:
@Autowired
private CallDomainPrepare callDomainPrepare;
@Test
@DisplayName("取消呼叫成功")
void should_cancel_call() {
// Call call = callDomainService.call(
// userFactory.createUser(),
// userFactory.createUser(),
// CallValues.builder()
// .build());
Call call = callDomainPrepare.prepareCallingCall(CallValues.builder().build());
callApplicationService.cancelCall(call.getId());
}
而在CallDomainPrepare中的实现则是:
// com.peng.project.domain.entity.CallDomainPrepare
@Autowired
private TestUserFactory userFactory;
public Call prepareCallingCall(CallValues callValues) {
User fromUser = userFactory.createUser();
User targetUser = userFactory.createUser();
return callDomainService.call(fromUser, targetUser, callValues);
}
这么做可以让在测试目录下定义的一些类都可以被复用到,不用再重复创建一遍。在多模块的项目中非常有用,可以加快测试代码编写的速度。