最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

java - Issue with Manually Setting ID in Spring Boot Integration Test with WebTestClient - Stack Overflow

programmeradmin1浏览0评论

Issue with Manually Setting ID in Spring Boot Integration Test with WebTestClient I am writing an integration test for my Spring Boot controller using WebTestClient. However, when I manually set the id of an Employee entity before saving it in my test, the test fails. If I remove the manual id assignment, the test passes.

Employee Entity

@Getter
@Setter
@Entity
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Employee {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(unique = true)
    private String email;

    private String name;
    private Long salary;
}

Employee Entity

@AutoConfigureWebTestClient(timeout = "100000")
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@Import(TestContainerConfiguration.class)
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class EmployeeControllerTestIT {

    @Autowired
    WebTestClient webTestClient;

    @Autowired
    private EmployeeRepository employeeRepository;

    private Employee testEmployee;
    private EmployeeDto testEmployeeDto;

    @BeforeEach
    void setUp() {
        employeeRepository.deleteAll();
        
        Long id = 1L;
        testEmployee = Employee.builder()
                .id(id) // Manually setting the ID
                .email("[email protected]")
                .name("Anuj")
                .salary(200L)
                .build();
        
        testEmployeeDto = EmployeeDto.builder()
                .id(id)
                .email("[email protected]")
                .name("Anuj")
                .salary(200L)
                .build();
    }

    @Test
    void testGetEmployeeById_success() {
        Employee savedEmployee = employeeRepository.save(testEmployee); // Fails here with error - .springframework.orm.ObjectOptimisticLockingFailureException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.springboot.testing.entities.Employee#1]
        
        webTestClient.get()
                .uri("/employees/{id}", savedEmployee.getId())
                .exchange()
                .expectStatus().isOk()
                .expectBody()
                .jsonPath("$.id").isEqualTo(savedEmployee.getId())
                .jsonPath("$.email").isEqualTo(savedEmployee.getEmail());
    }
}

Issue

If I manually set the ID, employeeRepository.save(testEmployee) fails.

If I remove the manual ID assignment, the test passes.

The course I am following shows their test working even with a manually set ID.

Question

Why does manually setting the ID cause save() to fail in my test, even though it works in the course I am following? How can I debug or resolve this issue?

Additional Info

I am using PostgreSQL as the database.

@GeneratedValue(strategy = GenerationType.IDENTITY) is used for ID generation.

I am using TestContainers for integration testing.

What could be causing this issue, and what would be the best approach to fix it?

Issue with Manually Setting ID in Spring Boot Integration Test with WebTestClient I am writing an integration test for my Spring Boot controller using WebTestClient. However, when I manually set the id of an Employee entity before saving it in my test, the test fails. If I remove the manual id assignment, the test passes.

Employee Entity

@Getter
@Setter
@Entity
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Employee {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(unique = true)
    private String email;

    private String name;
    private Long salary;
}

Employee Entity

@AutoConfigureWebTestClient(timeout = "100000")
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@Import(TestContainerConfiguration.class)
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class EmployeeControllerTestIT {

    @Autowired
    WebTestClient webTestClient;

    @Autowired
    private EmployeeRepository employeeRepository;

    private Employee testEmployee;
    private EmployeeDto testEmployeeDto;

    @BeforeEach
    void setUp() {
        employeeRepository.deleteAll();
        
        Long id = 1L;
        testEmployee = Employee.builder()
                .id(id) // Manually setting the ID
                .email("[email protected]")
                .name("Anuj")
                .salary(200L)
                .build();
        
        testEmployeeDto = EmployeeDto.builder()
                .id(id)
                .email("[email protected]")
                .name("Anuj")
                .salary(200L)
                .build();
    }

    @Test
    void testGetEmployeeById_success() {
        Employee savedEmployee = employeeRepository.save(testEmployee); // Fails here with error - .springframework.orm.ObjectOptimisticLockingFailureException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.springboot.testing.entities.Employee#1]
        
        webTestClient.get()
                .uri("/employees/{id}", savedEmployee.getId())
                .exchange()
                .expectStatus().isOk()
                .expectBody()
                .jsonPath("$.id").isEqualTo(savedEmployee.getId())
                .jsonPath("$.email").isEqualTo(savedEmployee.getEmail());
    }
}

Issue

If I manually set the ID, employeeRepository.save(testEmployee) fails.

If I remove the manual ID assignment, the test passes.

The course I am following shows their test working even with a manually set ID.

Question

Why does manually setting the ID cause save() to fail in my test, even though it works in the course I am following? How can I debug or resolve this issue?

Additional Info

I am using PostgreSQL as the database.

@GeneratedValue(strategy = GenerationType.IDENTITY) is used for ID generation.

I am using TestContainers for integration testing.

What could be causing this issue, and what would be the best approach to fix it?

Share Improve this question asked Feb 15 at 16:06 ADITYA RAJADITYA RAJ 3251 gold badge4 silver badges10 bronze badges 1
  • pls add exception stacktrace to your question – Geii Lvov Commented Feb 16 at 8:35
Add a comment  | 

1 Answer 1

Reset to default 1

Your entity is defined as

    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

And the code failing is

    Long id = 1L;
    
    testEmployee = Employee.builder()
            .id(id) // Manually setting the ID
            .email("[email protected]")
            .name("Anuj")
            .salary(200L)
            .build();

    Employee savedEmployee = employeeRepository.save(testEmployee); 

with error

.springframework.orm.ObjectOptimisticLockingFailureException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.springboot.testing.entities.Employee#1]

Then to your

Question

Why does manually setting the ID cause save() to fail in my test

Error Root cause:

Since you have defined the entity with strategy = GenerationType.IDENTITY) the creation of ID is happening in PostgreSQL Database. Neither your code nor hibernate is used to create the entity id.

For this reason the database row for that entity is created with the ID created from database. Then most probably since you provide also an ID to your save method, hibernate executes an additional statement to update the ID column with your custom provided ID. This is prohibited and hence the error.

More useful information in this previous answer. and in this PostgeSQL documentation

发布评论

评论列表(0)

  1. 暂无评论