单元测试中如何设置JPA实体被AccessLevel.NONE修饰的属性?
如何设置被
@Setter(AccessLevel.NONE)修饰的字段 当然有办法!针对你遇到的场景,这里有几种实用的解决方案:
方法1:使用Java反射(最直接,无需修改实体类)
Java反射可以绕过访问权限限制,直接给私有字段赋值。你可以在测试方法里添加这段代码:
@Test public void testGetName() { int id = 2; User mockUser = new User(); mockUser.setName("John"); // 用反射设置id字段 try { Field idField = User.class.getDeclaredField("id"); idField.setAccessible(true); // 开启访问权限 idField.set(mockUser, id); } catch (NoSuchFieldException | IllegalAccessException e) { e.printStackTrace(); // 或者根据测试需要抛出RuntimeException throw new RuntimeException("Failed to set id via reflection", e); } Optional<User> mockUserOptional = Optional.of(mockUser); Mockito.when(userRepository.findById(id)).thenReturn(mockUserOptional); // 后续测试逻辑... }
这种方法不需要修改你的实体类代码,非常适合临时测试场景。
方法2:给实体类添加测试友好的构造方法
如果你愿意微调实体类,可以添加一个包含id参数的构造方法,专门用于测试:
@NoArgsConstructor @Data @Entity public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Setter(AccessLevel.NONE) private int id; @Column(nullable = false) private String name; // 测试专用构造方法,包级访问权限即可(测试类和实体类同包的话) User(int id, String name) { this.id = id; this.name = name; } }
然后在测试里直接用这个构造方法创建对象:
@Test public void testGetName() { int id = 2; User mockUser = new User(id, "John"); // 直接用测试构造方法 Optional<User> mockUserOptional = Optional.of(mockUser); Mockito.when(userRepository.findById(id)).thenReturn(mockUserOptional); // 后续测试逻辑... }
这种方式更优雅,也避免了反射的复杂性。如果测试类和实体类不在同一个包,可以把构造方法的权限改成protected,或者用@VisibleForTesting注解(来自Google Guava或Spring Framework)标记,明确表示这个构造方法是为测试设计的。
方法3:使用Lombok的@Builder(可选)
如果你已经用了Lombok,可以给实体类添加@Builder注解,然后通过Builder来设置id字段:
@NoArgsConstructor @Data @Entity @Builder public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Setter(AccessLevel.NONE) private int id; @Column(nullable = false) private String name; // 手动添加全参构造方法,适配@Builder(Lombok自动生成可能受@NoArgsConstructor影响) @Builder private User(int id, String name) { this.id = id; this.name = name; } }
然后在测试里这样用:
@Test public void testGetName() { int id = 2; User mockUser = User.builder().id(id).name("John").build(); Optional<User> mockUserOptional = Optional.of(mockUser); Mockito.when(userRepository.findById(id)).thenReturn(mockUserOptional); // 后续测试逻辑... }
这种方式适合本来就用Builder模式的项目,代码更简洁。
内容的提问来源于stack exchange,提问作者Phurinat Puekkham
相关产品推荐
相关产品推荐

