Lombok @Builder多构造器继承场景下字段初始化失败问题
Lombok @Builder 继承场景下部分字段初始化失败问题
问题说明
抽象父类EventDTO被CreateTaskLogDTO继承,两者各定义了两个构造器,子类构造器分别调用父类对应的构造器。其中标注@Builder(builderMethodName = "buildWithSpecificParamsNoID")的构造器工作正常,但标注@Builder(builderMethodName = "buildWithOperationStringID")的构造器无法初始化Long id和String operationString字段。测试验证发现:
- 使用
buildWithOperationStringID构建对象时,id和operationString字段未被正确设置,其余字段正常 - 使用
buildWithSpecificParamsNoID构建对象时,所有字段均可正常初始化
父类 EventDTO 源码
package com.wwme.wwme.log.domain.DTO; import com.wwme.wwme.group.domain.Group; import com.wwme.wwme.log.domain.OperationType; import com.wwme.wwme.task.domain.Task; import com.wwme.wwme.user.domain.User; import lombok.Getter; import lombok.Setter; import java.time.LocalDateTime; @Getter @Setter public abstract class EventDTO { public EventDTO(Long id, User user, Group group, OperationType operationTypeEnum, LocalDateTime operationTime, String operationString, Task task) { this.id = id; this.user = user; this.group = group; this.operationTypeEnum = operationTypeEnum; this.operationTime = operationTime; this.operationString = operationString; this.task = task; } public EventDTO(User user, Group group, OperationType operationTypeEnum, LocalDateTime operationTime, Task task) { this.user = user; this.group = group; this.operationTypeEnum = operationTypeEnum; this.operationTime = operationTime; this.task = task; } protected Long id; protected User user; protected Group group; protected Task task; protected OperationType operationTypeEnum; protected LocalDateTime operationTime; protected String operationString; //Calculate Operation String based on given parameters public abstract void setOperationStr(); @Override public String toString() { return "EventDTO{" + "id=" + id + ", user=" + user.getNickname() + ", group=" + group.getGroupName() + ", task=" + task.getTaskName() + ", operationTypeEnum=" + operationTypeEnum + ", operationTime=" + operationTime + ", operationString='" + operationString + '\'' + '}'; } //set specific fields for public abstract void setSpecificFields(); public abstract String convertToString(); }
子类 CreateTaskLogDTO 源码
package com.wwme.wwme.log.domain.DTO; import com.wwme.wwme.group.domain.Group; import com.wwme.wwme.log.domain.OperationType; import com.wwme.wwme.task.domain.Task; import com.wwme.wwme.user.domain.User; import lombok.Builder; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import java.time.LocalDateTime; @Slf4j @Getter public class CreateTaskLogDTO extends EventDTO{ private String newTaskName; @Builder(builderMethodName = "buildWithSpecificParamsNoID") public CreateTaskLogDTO(User user, Group group, OperationType operationTypeEnum, LocalDateTime operationTime, String newTaskName, Task task) { super(user, group, operationTypeEnum, operationTime, task); this.newTaskName = newTaskName; setOperationStr(); } @Builder(builderMethodName = "buildWithOperationStringID") //buildWithOperationStringID public CreateTaskLogDTO(Long id, User user, Group group, OperationType operationTypeEnum, LocalDateTime operationTime, String operationString, Task task) { super(id, user, group, operationTypeEnum, operationTime, operationString, task); setSpecificFields(); } @Override public String toString() { return super.toString() + "CreateTaskLogDTO{" + "newTaskName='" + newTaskName + '\'' + ", operationString='" + operationString + '\'' + '}'; } @Override public void setOperationStr() { this.operationString = newTaskName; } @Override public void setSpecificFields() { this.newTaskName = this.getOperationString(); } @Override public String convertToString() { log.info(this.getUser().getNickname()); log.info(this.getNewTaskName()); return "\"" + this.getUser().getNickname() + "\" 님이 " + "\"" + this.getNewTaskName() +"\"" + "과제를 생성하였습니다."; } }
失败测试代码(使用 buildWithOperationStringID)
@Test void createTaskLogDTO_builder_withID_test(){ String operationString = "Task1"; LocalDateTime now = LocalDateTime.now(); when(mockTask.getTaskName()).thenReturn("Task1"); when(mockUser.getNickname()).thenReturn("User1"); when(mockGroup.getGroupName()).thenReturn("Group1"); CreateTaskLogDTO createTaskLogDTO = CreateTaskLogDTO.buildWithOperationStringID() .id(1L) .task(mockTask) .user(mockUser) .group(mockGroup) .operationString(operationString) .operationTime(now) .operationTypeEnum(OperationType.CREATE_TASK) .build(); assertEquals(createTaskLogDTO.getId(),1L); assertEquals(createTaskLogDTO.getTask().getTaskName(),mockTask.getTaskName()); assertEquals(createTaskLogDTO.getUser().getNickname(),mockUser.getNickname()); assertEquals(createTaskLogDTO.getGroup().getGroupName(),mockGroup.getGroupName()); assertEquals(createTaskLogDTO.getOperationTime(),now); assertEquals(createTaskLogDTO.getOperationTypeEnum(),OperationType.CREATE_TASK); assertEquals(operationString,createTaskLogDTO.getOperationString()); }
成功测试代码(使用 buildWithSpecificParamsNoID)
@Test void createTaskLogDTO_build_withoutID_test(){ when(mockTask.getTaskName()).thenReturn("Task1"); when(mockUser.getNickname()).thenReturn("User1"); when(mockGroup.getGroupName()).thenReturn("Group1"); String operationString = "Task1"; LocalDateTime now = LocalDateTime.now(); CreateTaskLogDTO createTaskLogDTO = CreateTaskLogDTO.buildWithSpecificParamsNoID() .task(mockTask) .user(mockUser) .group(mockGroup) .operationTime(now) .operationTypeEnum(OperationType.CREATE_TASK) .newTaskName(mockTask.getTaskName()) .build(); assertEquals(createTaskLogDTO.getTask().getTaskName(),mockTask.getTaskName()); assertEquals(createTaskLogDTO.getUser().getNickname(),mockUser.getNickname()); assertEquals(createTaskLogDTO.getGroup().getGroupName(),mockGroup.getGroupName()); assertEquals(createTaskLogDTO.getOperationTime(),now); assertEquals(createTaskLogDTO.getOperationTypeEnum(),OperationType.CREATE_TASK); assertEquals(operationString,createTaskLogDTO.getOperationString()); assertEquals(mockTask.getTaskName(),createTaskLogDTO.getNewTaskName()); }
内容的提问来源于stack exchange,提问作者Doh Kun Lee sanity
相关产品推荐
相关产品推荐

