news 2026/10/1 9:27:55

Squaretest实战:让IDEA自动生成可运行的Mockito单元测试

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Squaretest实战:让IDEA自动生成可运行的Mockito单元测试

1. 为什么说“写完测试还能跑通”才是真本事

我先描述一个场景,你看看是不是似曾相识:UserService里有个方法registerUser,内部依赖UserMapper做数据库写入、EmailClient发欢迎邮件、KafkaProducer发注册事件,还要做用户名唯一性校验。让你为这个方法写单元测试,你大概率会打开 IDE,右键 → Generate → Test,看着 IDEA 自动生成一个测试类骨架——里面所有依赖都是null,方法体全是TODO。然后你开始手动补Mockito.mock()、when().thenReturn()、verify(),一个方法写完,三四十行代码没了,而且一半时间花在“怎么把UserMapper那个@Autowired依赖注入进去”这种体力活上。

这就是我接触到 Squaretest 之前的状态:单元测试覆盖率报表上数字挺好看,但实际写起来特别痛苦,一个新来的同事光是学会怎么给LocalDateTime.now()打桩就要折腾一个小时。

Squaretest 是 IntelliJ IDEA 上的一个付费插件,干的事情可以概括成一句话:选中一个类,右键一点,自动生成基于 Mockito 的可运行的单元测试代码。它分析你类里的构造器、字段依赖、方法签名、返回值类型,然后自动创建@Mock、@InjectMocks,给每个被调用的依赖方法生成when().thenReturn()打桩,甚至主动生成verify()断言来校验方法间的交互顺序。

这篇文章我把自己从安装到实测、再到现在日常使用的完整过程拆开讲,适合正在为 Java 单元测试秃头的后端开发,也适合那些“知道要写测试但一直没时间系统学 Mockito”的团队新人。我尽量把每个关键操作都解释清楚为什么这样做,而不是只给一步抄一步的清单。

2. Mock 单元测试的三种写法,为什么 Squaretest 选了最难的那个

深入插件本身之前,先聊清楚一个根本问题:Mock 单元测试到底该怎么生成。市面上其实有三条技术路线,Squaretest 选的是第三条,也是技术上最激进的那条。

2.1 反射注入式——最简单的路,但代码质量最差

IDEA 自带的测试生成器走的是这条路。它扫描被测类的字段,生成@Before方法,然后在里面写一堆unsafe方式的反射赋值,或者干脆留空让你自己填。

这种方式生成的测试类有个通病:测试方法和被测方法之间没有“契约感”。你调用userService.registerUser(user),但userMapper是null,跑到userMapper.insert(user)那行直接 NullPointerException,你还得手动去 mock 所有依赖。写得多了你会发现,所谓“自动生成测试”其实就是“自动生成了个测试文件”,九成代码还是要自己写。

2.2 轻量占位式——看着能用,实际上跑不起来

有段时间我试过 IDEA 的Generate Test Methods结合 Live Template 的方式,它在测试类里给每个被测方法生成空方法壳,然后配合org.mockito.Mockito.mock()在字段声明处直接初始化:

private UserMapper userMapper = Mockito.mock(UserMapper.class);

这段代码能编译能运行,但你运行测试时看到的全是FAILED,因为所有 mock 对象的方法调用默认返回null或原始值,而你没有写任何when().thenReturn()。这种生成器的价值约等于帮你敲好了类名和方法名,仅此而已。

2.3 静态分析 + 交互式打桩——Squaretest 的路

Squaretest 的生成逻辑是第一代和第二代的深度融合:它先对被测类做字节码级别的静态分析,识别出所有实例字段和构造器参数,确定哪些需要 mock。然后针对每个测试方法,追踪被测方法内部对依赖对象的调用链,为每个调用生成合理的when打桩。

举个例子,UserService.registerUser里调用了userMapper.selectByUsername(username),Squaretest 会给这个方法生成类似这样的打桩:

User user = new User(); when(userMapper.selectByUsername(anyString())).thenReturn(null);

它甚至分析出selectByUsername返回的是User对象,所以自动new了一个User实例作为返回值,还贴心地生成了anyString()匹配器。这就是“自动生成”四个字的真实含金量:它不仅输出结构,还在替你思考“这个依赖方法需要返回什么东西,测试才能往下走”。

生成方式依赖分析能力打桩生成断言生成可运行性
IDEA 原生生成器无,仅生成文件壳无无法生成不可直接运行
Live Template 轻量生成弱,仅 mock 字段无无法生成编译通过但运行失败
Squaretest强,字节码级分析依赖调用自动生成 when/thenReturn生成 verify 和基本 assert多数情况下可直接运行

Squaretest 在技术上更接近“读取你代码的语义,然后映射成对应的 Mockito 语句”,而不是简单拼接代码字符串。它能做到这一点,核心原因是它分析的是编译后的字节码,而 IDEA 原生生成器只做了源码层面的简单匹配。这也是为什么它生成出来的测试比 IDEA 自带的“像样”很多。

3. 环境准备和首次生成:从安装到跑通第一个 Mock 测试

工具选型聊完,进入实操环节。这一节我把自己第一次从零配置到跑通测试的过程原原本本写出来,包括中途踩的几个小坑。

3.1 依赖配置:JUnit + Mockito + 必要的辅助库

Squaretest 只为 IDEA 插件市场提供安装包,它本身不做测试框架。它生成的代码默认依赖 JUnit 4 和 Mockito,所以你项目的build.gradle里需要先有这些基础依赖:

dependencies { testImplementation 'junit:junit:4.13.2' testImplementation 'org.mockito:mockito-core:4.11.0' testImplementation 'org.mockito:mockito-inline:4.11.0' testImplementation 'org.springframework:spring-test:5.3.30' }

这里有几个选型细节值得展开:

  • JUnit 4 是 Squaretest 的默认目标框架。虽然新版 Squaretest 也支持 JUnit 5(Jupiter),但我实际用下来,JUnit 4 + MockitoJUnitRunner 的生成代码在稳定性上表现最好。如果项目是纯 JUnit 5,注意在生成选项里手动切换 Test Framework,否则生成代码虽然看着正常,但@RunWith注解会直接报红。
  • mockito-inline 这个依赖,很多人忽略,但它非常关键。它让 Mockito 支持 mock 静态方法和final类,这两个能力在测试 Java 后端的工具类、配置类时几乎是刚需。不加这个依赖,Squaretest 生成的某些mockStatic代码会直接抛MockitoException,报错信息还很隐蔽,说“static mocking is not supported”。
  • spring-test 不是必需项,但如果你被测类里有@Value注入、@Autowired字段这类 Spring 注解,Squaretest 可能会用到ReflectionTestUtils来辅助注入,事先引入能避免生成代码里出现 import 报错。

注意:如果项目里同时存在 JUnit 4 和 JUnit 5 的依赖,建议在测试代码里统一用 JUnit 4 的org.junit.Test注解,避免 Squaretest 生成时产生混合依赖的混乱。

3.2 插件安装:Community 版装不了,别白费功夫

Squaretest 在 IntelliJ IDEA 插件市场搜得到,安装过程本身没什么好说的,但有一个特别容易踩的坑:IntelliJ IDEA Community Edition(社区版)不支持这个插件。

当年我就是被这一点坑过。公司配的电脑上装的是社区版,我兴致勃勃地在插件市场搜到 Squaretest,点击 Install,结果按钮直接置灰,下方一行小字提示:Only available in IntelliJ IDEA Ultimate。社区版本质上是个轻量级 IDE,不包含商业插件的基础框架支持,这类测试生成类插件全都用不了。

所以如果你现在是社区版,想要原生体验 Squaretest,就得让公司申请 Ultimate 授权。如果实在没有条件,退而求其次的替代方案是:把项目代码帮你生成测试的人装一个 Ultimate,生成后的测试代码直接提交到仓库,其他人就能在同一份代码上继续开发。

插件装好后,Preferences → Plugins → Squaretest里能看到配置项。需要注意两个选项:

  • Mockito Static Mocking:默认开启,推荐保持打开。关闭后生成代码里遇到静态方法会直接忽略,测试很容易在静态方法调用处报 NPE。
  • Detect Spring @Autowired Fields:默认开启。如果不开启,Squaretest 会将@Autowired字段当成普通字段处理,生成的@InjectMocks注入顺序可能出问题,某些依赖 mock 进去了但when打桩指向错误对象。

3.3 第一次生成:右键的一小步,单元测试的一大步

在 IDE 里打开被测类,右键类名 → Generate → Squaretest → OK,插件会在src/test/java的对应包路径下生成一个测试类。

我用一个典型的三层应用服务类做演示,被测类是UserService:

public class UserService { private final UserMapper userMapper; private final EmailClient emailClient; private final KafkaProducer kafkaProducer; public UserService(UserMapper userMapper, EmailClient emailClient, KafkaProducer kafkaProducer) { this.userMapper = userMapper; this.emailClient = emailClient; this.kafkaProducer = kafkaProducer; } public User registerUser(UserRegistrationRequest request) { String username = request.getUsername(); User existing = userMapper.selectByUsername(username); if (existing != null) { throw new BusinessException("USERNAME_ALREADY_EXISTS"); } User user = User.createNewUser(request); userMapper.insert(user); emailClient.sendWelcomeEmail(user.getEmail()); kafkaProducer.send("USER_REGISTERED", user.getId()); return user; } }

Squaretest 生成的测试类长这样(截取核心部分):

@RunWith(MockitoJUnitRunner.class) public class UserServiceTest { @Mock private UserMapper userMapper; @Mock private EmailClient emailClient; @Mock private KafkaProducer kafkaProducer; @InjectMocks private UserService userService; @Before public void setUp() { // Squaretest generated setup } @Test public void testRegisterUser_Success() throws Exception { UserRegistrationRequest request = new UserRegistrationRequest(); // setUp for request when(userMapper.selectByUsername(anyString())).thenReturn(null); User result = userService.registerUser(request); // assert result verify(userMapper).insert(any(User.class)); verify(emailClient).sendWelcomeEmail(anyString()); verify(kafkaProducer).send(eq("USER_REGISTERED"), anyString()); } }

看到了吧,这就是前面说的“静态分析 + 交互式打桩”的成果。@Mock自动创建了三个依赖的 mock 对象,@InjectMocks把 mock 注入到被测类的构造器里,when(userMapper.selectByUsername(...)).thenReturn(null)对应被测方法里第一个依赖调用,verify系列是插件根据被测方法内部所有依赖交互自动生成的断言。

不过这里有个细节我非常想提醒:Squaretest 生成的断言偏“交互验证”型,而不是“状态验证”型。也就是说,它更关注“你有没有调用 emailClient.sendWelcomeEmail”,而不是“返回值里的 email 字段是否等于 request.getEmail()”。前者适合验证流程,后者适合验证数据正确性。实际使用中我一般会手动在assert result注释处补上状态断言,比如:

assertNotNull(result.getId()); assertEquals(request.getUsername(), result.getUsername());

4. 生成代码的边界和常见问题:为什么有些测试跑不过去

工具再聪明,它也不会读心术。Squaretest 生成的测试类里有很多地方需要人工介入,这部分才是真正区分“会用插件”和“用好插件”的分界线。

4.1 数据对象创建:new出来的对象字段全空

Squaretest 没有办法知道你的请求对象哪个字段对业务逻辑至关重要,它只能创建一个对象,然后让所有字段保持默认值(null、0、false)。

这里的问题在于:很多业务代码里,registerUser内部第一行就是String username = request.getUsername();,然后selectByUsername(username)打桩用了anyString(),这没问题。但如果被测方法内部对某个字段做了非空判断:

if (request.getEmail() == null) { throw new IllegalArgumentException("email is required"); }

那么 Squaretest 生成的测试就会在这里直接抛异常,断言失败,测试标红。这不是插件 bug,而是它无法理解“email 是必填项”这种领域规则。

我的处理方式是把数据准备抽成一个 helper 方法,每次生成后统一调用:

private UserRegistrationRequest createValidRequest() { UserRegistrationRequest request = new UserRegistrationRequest(); request.setUsername("alice"); request.setEmail("alice@example.com"); request.setPassword("secret"); return request; }

生成完代码后,把new UserRegistrationRequest()替换成createValidRequest(),全局一次性修完。实测下来效率提升非常明显。

4.2 被测方法里同步调用静态方法或 final 方法

Squaretest 生成的测试代码能处理一部分LocalDate.now()、UUID.randomUUID()这类 JDK 静态方法,但它们的处理方式比较粗暴——直接不打桩,保留真实调用。

这在大多数情况下没问题:UUID.randomUUID()的真实行为是稳定且幂等的,不会影响测试结果。但如果你被测方法内部有:

public String generateUsername(UserRegistrationRequest request) { return request.getUsername() + "_" + RandomStringUtils.randomAlphanumeric(6); }

那么每次运行测试,RandomStringUtils都会生成不同随机值,如果断言依赖这个生成结果,测试就会变成“间歇性通过/失败”的 flaky test。

这种情况下,我推荐的方案分两步:

第一,给generateUsername方法内部引入一个可注入的RandomString服务,而不是直接在方法里new一个静态工具:

public class UserService { private final RandomStringGenerator randomStringGenerator; // 构造器注入 }

第二层思路才是用mockito-inline配合try-with-resources做静态方法的局部 mock:

try (MockedStatic<RandomStringUtils> mocked = mockStatic(RandomStringUtils.class)) { mocked.when(() -> RandomStringUtils.randomAlphanumeric(6)) .thenReturn("abc123"); // 调用被测方法并断言 }

这里我想拎出来单说一句:能用依赖注入解决的问题,不要依赖静态 mock。静态 mock 写起来麻烦,而且只对当前线程有效,多线程测试容易出问题。Squaretest 对这类场景通常只能做到“生成一个建议性的注释”,没有能力自动写出可靠的静态打桩,所以人工介入不可避免。

4.3 私有方法无法直接测试

Squaretest 生成的测试方法只覆盖被测类里的public方法。如果你的业务类里有一个逻辑复杂的private void validateUser(User user)方法,Squaretest 不会生成针对它的直接测试。

这倒不能怪插件,private方法本身就不是单元测试的主要目标。业界主流观点是:私有方法的逻辑需要通过它的 public 调用方来间接覆盖。如果你发现某个私有方法逻辑特别复杂、分支特别多,而你又特别想单独验证,最干净的方案是把它抽成独立的package-private类或工具类,再对它写测试。

我不建议用反射去调私有方法。反射测试私有方法的本质是把测试代码和实现细节耦合在一起,一旦你重命名了私有方法,测试代码立刻编译失败,这种维护成本远大于重构代码结构来换取可测试性。

4.4 构造器入口复杂:@InjectMocks的局限

Squaretest 的@InjectMocks对构造器注入、Setter 注入、字段注入都有一定的兼容能力。但有一个场景它处理得不好:构造器里存在非 mock 类型的入参。

比如你有一个配置类,构造器长这样:

public UserService(UserMapper userMapper, AppConfig config) { this.userMapper = userMapper; this.config = config; }

AppConfig是一个普通配置 POJO,不需要 mock,保持真实对象比较好。Squaretest 默认会把所有入参都 mock 掉,这也无可厚非,但生成出来的when(config.getSomeParam()).thenReturn("...")这种打桩反而显得多余。

针对这种情况,我一般是在生成测试类后手动删掉@Mock AppConfig,然后在@Before里 new 一个真实的AppConfig对象并设置必要字段,再替换@InjectMocks为手动构造:

private UserService userService; @Before public void setUp() { AppConfig config = new AppConfig(); config.setMaxRetryTimes(3); userService = new UserService(userMapper, config); }

这样处理的好处是测试意图更清晰:UserMapper是外部依赖需要 mock,AppConfig是基础配置直接使用真实值。

5. 从“跑通”到“跑稳”:生成代码的质量增强三板斧

如果你想拿 Squaretest 生成完的测试代码直接塞进 CI 流水线,多半会吃一堆“间歇性失败”的苦头。这一节分享我自己在生产和社区项目里调出来的三条增强策略,它们本质上是让生成代码更接近“一个懂业务的人手写的测试”。

5.1 断言向量化:给 verify 加上你真正关心的状态

前面提到过 Squaretest 生成的断言偏交互型。我建议在最终交付前对代码做一轮断言增强,思路是给目标状态建立“断言向量”:尽可能同时验证 switch 逻辑的分支走向和最终状态值。

以testRegisterUser_Success为例,除了 verify 三个依赖交互,至少要补上这几条断言:

assertNotNull(result.getId()); assertEquals("alice", result.getUsername()); assertTrue(result.getStatus().isActive()); assertEquals("USER_REGISTERED_PENDING", result.getWelcomeEmailStatus());

这里的核心逻辑是:一个测试用例,至少要有一个“反向可证伪”的状态断言。如果测试跑通了但完全没有状态断言,你根本不知道这个方法是不是真的把注册用户状态改成正确的值了。

另外,分支覆盖是一个常见的短板。Squaretest 会在被测方法每个分支都生成一个测试方法,比如testRegisterUser_WhenUsernameExists、testRegisterUser_WhenEmailInvalid等等。但它生成了分支测试方法不代表它能测试对分支条件。实际使用中,我把生成出来所有test*_When*的方法过一遍,给每个方法补上对应的 mock 打桩。

testRegisterUser_WhenUsernameExists里需要把:

when(userMapper.selectByUsername(anyString())).thenReturn(null);

改成:

User existingUser = new User(); existingUser.setUsername("alice"); when(userMapper.selectByUsername("alice")).thenReturn(existingUser);

这样这个测试方法才是真正运行在“用户名已存在”的分支上,不然它和成功分支的测试代码几乎一样,但又跑不过去。

5.2 填充数据准备区:给随机时间、金额、状态码留出可控入口

很多业务方法里会用到时间。LocalDateTime.now()如果不打桩,Sweetest 生成的方法在早上跑和晚上跑结果可能不一样,尤其是那些有“过期时间”“创建时间”限定的逻辑。

Squaretest 不会自动打桩时间相关代码,但业务代码如果设计成接收一个Clock参数,就能轻松解决:

public class UserService { private final Clock clock; public UserService(UserMapper userMapper, EmailClient emailClient, KafkaProducer kafkaProducer, Clock clock) { // ... this.clock = clock; } public User registerUser(UserRegistrationRequest request) { LocalDateTime now = LocalDateTime.now(clock); // 用 now 设置创建时间、过期时间 } }

单元测试里写:

Clock fixedClock = Clock.fixed( Instant.parse("2025-01-15T10:00:00Z"), ZoneId.of("Asia/Shanghai") );

把fixedClock传入构造器,所有时间相关断言都变成确定性的了。这个方法不复杂,但能省掉一大把“为什么早上跑测试就挂了”的 Debug 时间。

5.3 依赖边界划分:识别哪些类不该用 Squaretest 生成测试

Squaretest 适合生成业务服务类、调用外部接口的 Manager/Client、包含判断逻辑的领域服务这类对象的测试。但有两类代码我不建议用它生成,硬用反而浪费时间:

  • 纯 DTO / POJO:没有逻辑,生成测试没有意义。
  • 包含了直接new多个复杂协作者的类:比如一个OrderService的构造器里new OrderValidator()、new OrderPriceCalculator()这种非注入的方式创建依赖,Squaretest 没法分析这些内部new出来的对象,生成的测试很容易出现“实际运行的是真实依赖而不是 mock”的状态,测试结果不可控。

遇到第二种情况,我最直接的方案是先重构被测类,把内部new的地方全部改成构造器注入,再跑 Squaretest。这个顺序不能反,反了生成的测试就是给自己埋雷。

6. 覆盖率和测试数据的真实关系:自动生成能拉高多少分

说完代码生成本身,最后聊一个我在团队里感触最深的话题:Squaretest 自动生成的测试对覆盖率数字的影响,以及这个数字背后的真实意义。

6.1 行覆盖率提升很快,但分支覆盖率才是硬骨头

Squaretest 生成一个测试类后,行覆盖率(Line Coverage)通常能直接拉到 60%~80%。原因是它给每个可调用的依赖都打了桩,被测方法里的主线逻辑基本都会被执行到。我拿一个约 300 行代码的服务类试过,生成 15 个测试方法后,行覆盖率从 8% 涨到 74%,速度非常惊人。

但分支覆盖率(Branch Coverage)就没那么乐观了。原因是 Squaretest 对if分支的处理策略是“每个分支生成一个测试方法”,但生成方法内部需要手动补打桩和断言,不补无法通过。所以分支覆盖率完全取决于你后续人工修改的深度。

这也是我想重点强调的:Squaretest 的定位是帮你敲代码,不是帮你思考测试策略。它把一张白纸变成一张有线条的画,但最重要的那些触笔,比如“用户名已存在分支的selectByUsername要返回已存在用户”“insert失败时会不会回滚”这些基于业务语义的判断,必须你来完成。

6.2 当覆盖率达到目标后,下一步该做什么

我自己用下来,Squaretest 拉满覆盖率之后,我反而会去关注那些插件没法生成的东西:

  • 异常路径和不合法数据:比如request.getUsername()是空字符串、超长字符串、包含特殊字符的时候,被测方法是否依然行为正确。
  • 并发场景:两个请求同时注册相同用户名,是否只有一个能成功。这个类场景单元测试很难测,直接用集成测试跑会更合适。
  • 幂等与重复调用:同一个registerUser调用两次,第二次应该报业务异常而不是插入重复数据。这类逻辑 Squaretest 生成的测试往往不能覆盖。

覆盖率是一个门槛性指标,不是质量指标。Squaretest 能让你的代码快速跨过 CI 门槛,但最终测试有没有价值,还是看你有没有在上面补足“业务语义”那一层。

6.3 可测试性设计的反哺:用起来之后,你的代码会变好

这是我最意外的收获。以前写业务代码,构造器注入写不写无所谓,反正 Spring 能自动装配;私有方法抽不抽取无所谓,反正编译能过就行。但如果你的团队把 Squaretest 作为日常开发工具,大家会不自觉地往“可测试性”方向调整代码风格:

  • 减少内部new,改成构造器注入;
  • 减少静态方法里的随机值和Thread.sleep,改成参数传入或依赖注入;
  • 把复杂私有方法抽成独立的公开工具类。

这些调整和设计模式无关,纯粹是“为了让 Squaretest 生成质量更高”这个诉求倒逼出来的好习惯。工具不会改变你的架构能力,但它会无声地引导你把代码写到更易被自动化测试检查的形态里。

7. 线程池和限量问题:生成大量测试类时容易忽略的性能细节

这一节算是我个人使用过程中的一个补充踩坑记录。项目代码达到一定规模后,我一次性对一个包下十几个 service 类生成测试,接着跑全量单测,发现构建时间从几分钟拉长到十几分钟,而且频繁出现OOM或MockitoException: Mockito is currently self-attaching之类的报错。

排查之后,问题出在几个地方:

  1. mockito-inline 的静态 mock 机制导致每个测试类加载时都会做额外的字节码插桩,类一多,内存占用显著上升。如果你的项目里生成了几十个测试类,建议在gradle.properties里调大测试 JVM 内存:
org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=1g
  1. 测试类的并行执行冲突。Gradle默认maxParallelForks=1,多数项目不会遇到。但如果你开了并行测试,多个测试类同时使用mockStatic会互相干扰。我的建议是:凡是try (MockedStatic...)这种静态 mock 代码,统一放到一个单独的测试类里串行执行,不要和普通并行任务混在一起。

  2. IDEA 本地生成时卡顿。Squaretest 在做字节码分析时对大型类会占用较多 CPU,如果你执行“Generate Tests for All Methods”且被测类有大量私有的复杂分支,界面可能会假死几秒。这不是死机,是分析过程。建议对复杂类分批生成,先生成单个方法,确认结果无误后再全量生成。

这些细节别人写教程的时候很少提,但实际到了多人协作的规模,不处理真的会拖垮构建流水线。

8. 最后:把自动生成当作“第一版草稿”而非最终交付物

我到现在用 Squaretest 已经大半年,最深的感受是:它最强的能力不是帮你把测试写完,而是帮你把“从无到有”这段最枯燥、最劝退新人的路程压缩到几秒钟。过去你要花一下午各种求助同事才会写的 Mockito 结构,现在右键一下就能得到 80 分的基础版本。剩下那 20 分——关键分支的 mock 数据、业务含义的状态断言、环境相关的特殊处理——这才是你作为开发者真正要动脑的地方。

如果你正打算引入这个插件,我的建议是:先拿一个你们系统里最典型的 service 类试跑一次,把生成的代码从头到尾读懂,感受一下插件对依赖分析的处理方式。然后挑一个不那么重要的方法,手工改断言、补分支、跑测试跑稳,体会一下“人工增强”和“自动生成”的配合节奏。等你完全理解了这套工作流,再把它推到团队里。

跑稳一波之后你会发现,单元测试门槛低了,大家更愿意写了,而更意外的是,你自己写业务代码的时候,会下意识开始考虑“这个类生成测试方不方便”。就冲这一点,这个插件的价值就已经超出了“省时间”本身。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/1 9:27:04

PermissionError 报错根治:pip 权限不足与虚拟环境解决方案

兄弟&#xff0c;看到PermissionError: [Errno 13] Permission denied这一行&#xff0c;是不是瞬间头皮发麻&#xff1f;别急&#xff0c;这基本上是每个玩 Python 的人都会碰到的一道坎&#xff0c;尤其是当你满心欢喜地 clone 了一个开源项目&#xff0c;准备用pip install …

作者头像 李华
网站建设 2026/10/1 9:26:23

跨平台二进制兼容实战:Wine、FEX-Emu与DXMT分层翻译解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/1 9:26:15

人力资源管理系统用例分析:登录、考勤到招聘的设计要点

简介&#xff1a;这是一份人力资源管理系统用例分析文档&#xff0c;主要面向软件工程课程设计、毕业设计或企业HR系统前期的需求分析工作。文档以用例图为抓手&#xff0c;系统梳理了登录、员工管理、考勤管理等模块的参与角色与功能流程&#xff0c;并延伸至招聘管理模块。其…

作者头像 李华
网站建设 2026/10/1 9:25:23

Java服务端OFD处理实战:解析、生成与踩坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/1 9:24:49

谷粒商城2020实战项目搭建与问题排查指南

简介&#xff1a;本资源是面向Java后端开发者与分布式系统学习者的微服务电商实战项目&#xff0c;聚焦高并发、高可用的分布式架构设计与落地。项目基于Spring Cloud Alibaba生态构建&#xff0c;完整覆盖微服务拆分、Nacos服务注册发现、Gateway网关统一接入、Seata分布式事务…

作者头像 李华
网站建设 2026/10/1 9:24:06

Linux文件关联与图标主题机制详解:基于freedesktop规范

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华