How to unit test pessimistic locking with Spring Boot + Spring Data JPA

I want to check if it works , after someone called it , others calling it have to wait. FooRepository.lock()

lock()

The following is my best attempt, it doesn't work. I believe that the reason is that entityManger

they fooRepository

are involved in the same transaction.

How to call lock()

from another transaction? Or any suggestion for unit testing pessimistic locking? Thank!!

FooRepositoryTest:

package com.example.demo;

import java.util.UUID;

import javax.persistence.LockModeType;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@DataJpaTest
public class FooRepositoryTest {

    @Autowired
    private TestEntityManager entityManager;    

    @Autowired
    private FooRepository fooRepository;

    @Test
    public void lockTest() {
        // given
        Foo foo = new Foo();
        foo.setName("foo-name");

        UUID fooId = fooRepository.save(foo).getFooId();
        entityManager.flush();
        entityManager.clear();

        // when
        Foo savedFoo = fooRepository.findOne(fooId);
        fooRepository.lock(savedFoo);

        // then
        // I want something like this to be lock wait,
        // something to confirm the above fooRepository.lock() work
        entityManager.getEntityManager().lock(savedFoo, LockModeType.PESSIMISTIC_WRITE);
    }

}

      

class Foo:

package com.example.demo;

import java.util.UUID;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class Foo {  
    @Id
    @GeneratedValue
    private UUID fooId;

    private String name;

    public UUID getFooId() {
        return fooId;
    }

    public void setFooId(UUID fooId) {
        this.fooId = fooId;
    }

    public String getName() {
        return name;
    }

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

}

      

FooApplication class:

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class FooApplication {

    public static void main(String[] args) {
        SpringApplication.run(FooApplication.class, args);
    }
}

      

FooRepository class:

package com.example.demo;

import java.util.UUID;

import org.springframework.data.jpa.repository.JpaRepository;

public interface FooRepository extends JpaRepository<Foo, UUID>, FooRepositoryCustom {  
}

      

FooRepositoryCustom class:

package com.example.demo;

public interface FooRepositoryCustom {  
    public void lock(Foo foo);  
}

      

FooRepositoryImpl class:

package com.example.demo;

import javax.persistence.EntityManager;
import javax.persistence.LockModeType;

import org.springframework.beans.factory.annotation.Autowired;

public class FooRepositoryImpl implements FooRepositoryCustom {

    @Autowired
    private EntityManager entityManager;

    @Override
    public void lock(Foo foo) {
        entityManager.lock(foo, LockModeType.PESSIMISTIC_WRITE);
    }   
}

      

+3


source to share


1 answer


You are getting unit testing wrong .

You are not doing a unit test write to implement the functionality implemented by some third party frameworks. Unit tests are designed for your devices!

In other words: you don't need to check that the lock is working as expected. Your block:

entityManager.lock(foo, LockModeType.PESSIMISTIC_WRITE);

      



so the only thing you can consider here is make sure the entity manager method lock()

is called with the expected parameters.

Meaning: Make sure your code actually uses the framework that you think you should use it, but don't get caught up in testing other people's code! You see - what would you do when your unit test shows the structure is wrong ... you cannot change that! (of course you can write a bug report)

Disclaimer: There may be special situations where you assume that some third party product has a bug - then it would be very helpful to write a unit test to test this assumption. So that you can later unit test against a newer version of that product to see if the bug is present.

+1


source







All Articles