Setter in DTO just for integration testing?

Viewed 50

I couldn't find the info I'm looking for hence posting here for suggestion and getting to know better approach.

I have an immutable DTO object like:

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.time.LocalDate;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class AccountCreateDto {
    String name;
    Long accountNo;
    String email;
    LocalDate dob;
    String address;
    Long phone;
    Integer amount;
    LocalDate accountOpeningDate;
    Integer installmentAmount;
    Integer totalAmount;
    LocalDate installmentPaidDate;

    @JsonCreator
    public AccountCreateDto(
            @JsonProperty("name") String name,
            @JsonProperty("accountNo") Long accountNo,
            @JsonProperty("email") String email,
            @JsonProperty("dob") LocalDate dob,
            @JsonProperty("address") String address,
            @JsonProperty("phone") Long phone,
            @JsonProperty("amount") Integer amount,
            @JsonProperty("accountOpeningDate") LocalDate accountOpeningDate,
            @JsonProperty("installmentAmount") Integer installmentAmount,
            @JsonProperty("totalAmount") Integer totalAmount,
            @JsonProperty("installmentPaidDate") LocalDate installmentPaidDate
    ) {
        this.name = name;
        this.accountNo = accountNo;
        this.email = email;
        this.dob = dob;
        this.address = address;
        this.phone = phone;
        this.amount = amount;
        this.accountOpeningDate = accountOpeningDate;
        this.installmentAmount = installmentAmount;
        this.totalAmount = totalAmount;
        this.installmentPaidDate = installmentPaidDate;
    }
    // removing getters for brevity
}

Now I'm working on an integration test with testcontainer where I want the accountOpeningDate and installmentPaidDate to be dynamic value hence in order to set these values from Integration Tests, is it a good idea to add only 2 setters to this DTO which is only to be used for Integration Tests like below?

    public void setAccountOpeningDate(LocalDate accountOpeningDate) {
        this.accountOpeningDate = accountOpeningDate;
    }

    public void setInstallmentPaidDate(LocalDate installmentPaidDate) {
        this.installmentPaidDate = installmentPaidDate;
    }

Or is there a better approach than this? Looking for recommendations.

TA

1 Answers

It is not acceptable you will lose the immutability of the object. With immutable classes, we can’t modify the state but must create a new instance with the mutated state.
The builder pattern is very useful in this case.
Example:

AccountCreateDto existingImmutableDTO = new AccountCreateDto("name", 1L, "name@aaa", LocalDate.now(), "Address", null, null, null, null, null, null );
        
//change state of imuttable object, create new instance via builder
AccountCreateDto modifiedImmutableDTO = new AccountCreateDtoBuilder(existingImmutableDTO).setAccountOpeningDate(LocalDate.now()).setInstallmentPaidDate(LocalDate.now()).build();
public class AccountCreateDtoBuilder {
    private String name;
    private Long accountNo;
    private String email;
    private LocalDate dob;
    private String address;
    private Long phone;
    private Integer amount;
    private LocalDate accountOpeningDate;
    private Integer installmentAmount;
    private Integer totalAmount;
    private LocalDate installmentPaidDate;

    public AccountCreateDtoBuilder() {
        
    }

    public AccountCreateDtoBuilder(AccountCreateDto accountCreateDto) {
        this.name = accountCreateDto.getName();
        this.accountNo = accountCreateDto.getAccountNo();
        this.email = accountCreateDto.getEmail();
        this.dob = accountCreateDto.getDob();
        this.address = accountCreateDto.getAddress();
        this.phone = accountCreateDto.getPhone();
        this.amount = accountCreateDto.getAmount();
        this.accountOpeningDate = accountCreateDto.getAccountOpeningDate();
        this.installmentAmount = accountCreateDto.getInstallmentAmount();
        this.totalAmount = accountCreateDto.getTotalAmount();
        this.installmentPaidDate = accountCreateDto.getInstallmentPaidDate();
    }

    public AccountCreateDto build() {
        return new AccountCreateDto(name, accountNo, email, dob, address, phone, amount, accountOpeningDate, installmentAmount, totalAmount, installmentPaidDate);
    }

    public AccountCreateDtoBuilder setName(String name) {
        this.name = name;
        return this;
    }

    public AccountCreateDtoBuilder setAccountNo(Long accountNo) {
        this.accountNo = accountNo;
        return this;
    }

    public AccountCreateDtoBuilder setEmail(String email) {
        this.email = email;
        return this;
    }

    public AccountCreateDtoBuilder setDob(LocalDate dob) {
        this.dob = dob;
        return this;
    }

    public AccountCreateDtoBuilder setAddress(String address) {
        this.address = address;
        return this;
    }

    public AccountCreateDtoBuilder setPhone(Long phone) {
        this.phone = phone;
        return this;
    }

    public AccountCreateDtoBuilder setAmount(Integer amount) {
        this.amount = amount;
        return this;
    }

    public AccountCreateDtoBuilder setAccountOpeningDate(LocalDate accountOpeningDate) {
        this.accountOpeningDate = accountOpeningDate;
        return this;
    }

    public AccountCreateDtoBuilder setInstallmentAmount(Integer installmentAmount) {
        this.installmentAmount = installmentAmount;
        return this;
    }

    public AccountCreateDtoBuilder setTotalAmount(Integer totalAmount) {
        this.totalAmount = totalAmount;
        return this;
    }

    public AccountCreateDtoBuilder setInstallmentPaidDate(LocalDate installmentPaidDate) {
        this.installmentPaidDate = installmentPaidDate;
        return this;
    }
}

Related