如何使用Junit和Spring手动提交事务

时间:2017-06-10 14:57:36

标签: java spring junit

我知道这不是什么新鲜事,但我尝试了几种方法而且它们没有用。 我是一个简单的Junit测试:

@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional
public class LicensePlateTests {

@Autowired
private LicensePlateRepository licensePlateRepository;

@Autowired
private CountryRepository countryRepository;

@Before
public void setup() {
    TestTransaction.start();
    Country country = new Country();
    country.setName("Italy");
    country.setIsoCode("IT");
    countryRepository.save(country);

    assertEquals(1, countryRepository.count());
}

@Test
public void saveLicensePlateAndChangeCheckAudited() {
        assertEquals(1, countryRepository.count());
        LicensePlate plate = new LicensePlate();
        plate.setLicensePlate("AA123BB");
        plate.setEngineEuroLevel(3);
        plate.setCoutry(countryRepository.findFirstByOrderByIdAsc());
        plate = licensePlateRepository.save(plate);             

        assertEquals(1, licensePlateRepository.count());

        plate.setEngineEuroLevel(5);
        plate = licensePlateRepository.save(plate);     

        //always 1 plate
        assertEquals(1, licensePlateRepository.count());

        //different version number
        assertEquals(2, plate.getVersion().intValue());

    }
}

此测试用例失败,因为版本号仍为1。

我所做的事情看起来有点奇怪但是这个测试只是部分完成,因为我在我的bean里面的几个属性上使用@Audited注释来跟踪变化。 我在这里尝试做的是检查版本号是否在更改后递增。我知道@Transactional只是在方法结束时提交事务,所以这解释了我的方法失败的原因。

我正在寻找的是一种在同一测试方法中进行多次提交的方法,但同时保留了从@Before方法到测试用例结束的事务的可见性。

要遵循哪些最佳做法?

=============================================== ================

我想我已经解决了我的问题。我不确定我的解决方案是一种最佳做法并且它很好,所以我不会将其作为回复发布。我认为它可能有用,所以这是完整的课程(我从https://github.com/spring-projects/spring-data-envers/blob/master/src/test/java/org/springframework/data/envers/repository/support/RepositoryIntegrationTests.java获得灵感)

     @RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
@TestPropertySource(locations = "classpath:test.properties")
public class LicensePlateAuditableTests {
    private Logger log = LogManager.getLogger();

    @Autowired
    private LicensePlateRepository licensePlateRepository;

    @Autowired
    private CountryRepository countryRepository;

    @Before
    public void setup() {
        licensePlateRepository.deleteAll();
        countryRepository.deleteAll();

        Country country = new Country();
        country.setName("Italy");
        country.setIsoCode("IT");
        countryRepository.save(country);        
    }



    @Test
    public void saveLicensePlateAndChangeCheckAudited() {
        assertEquals(1, countryRepository.count());

        LicensePlate plate = new LicensePlate();
        plate.setLicensePlate("AA123BB");
        plate.setEngineEuroLevel(3);
        plate.setCoutry(countryRepository.findFirstByOrderByIdAsc());
        plate = licensePlateRepository.save(plate);

        // First version number is 1
        assertEquals(1, plate.getVersion());

        // Changing some auditable data
        plate.setEngineEuroLevel(5);
        plate.setLicensePlate("AA956BB");
        plate = licensePlateRepository.save(plate);

        // different version number
        assertEquals(2, plate.getVersion());

        // I should have 2 revisions
        assertEquals(2, licensePlateRepository.findRevisions(plate.getId()).getContent().size());

        Revisions<Integer, LicensePlate> revisions = licensePlateRepository.findRevisions(plate.getId());

        int i = 1;
        for (Revision<Integer, LicensePlate> rev : revisions.getContent()) {
            if (i == 1) {
                // At the beginning the engine level was 3
                assertEquals(3, rev.getEntity().getEngineEuroLevel());
                // At the beginning the place number was AA123BB
                assertEquals("AA123BB", rev.getEntity().getLicensePlate());
            }

            if (i == 2) {
                // Then the engine level became 5
                assertEquals(5, rev.getEntity().getEngineEuroLevel());
                // Then the license plate number became AA956BB
                assertEquals("AA956BB", rev.getEntity().getLicensePlate());
            }
            i++;
        }

        // Check if the entry in the database has updated data
        assertEquals(5, licensePlateRepository.findOne(plate.getId()).getEngineEuroLevel());
        assertEquals("AA956BB", licensePlateRepository.findOne(plate.getId()).getLicensePlate());
    }

1 个答案:

答案 0 :(得分:1)

您在测试方法中的注释会提示您应该使用多少测试方法。 只是建议:您应该遵循一个适合您和您的团队的测试方法的名称约定。在我的项目中,我习惯于使用'check','verify'...以及我检查方法的解释用例来启动测试方法的名称。 像这样的东西(只是因为你没有展示真正的类),我试图展示测试方法名称的外观:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
@TestPropertySource(locations = "classpath:test.properties")
public class LicensePlateAuditableTests {
private Logger log = LogManager.getLogger();

@Autowired
private LicensePlateRepository licensePlateRepository;

@Autowired
private CountryRepository countryRepository;

private LicensePlate plate;
private final String PLATE_NUMBER_FIRST = "AA123BB";
private final String PLATE_NUMBER_SECOND = "AA956BB";
private int ENGINE_EURO_LEVEL_FIRST = 3;
private int ENGINE_EURO_LEVEL_SECOND = 3;

@Before
public void setup() {
    licensePlateRepository.deleteAll();
    countryRepository.deleteAll();

    Country country = new Country();
    country.setName("Italy");
    country.setIsoCode("IT");
    countryRepository.save(country);
}

@Test
public void checkThatVersionIsOneAfterCreateLicensePlate() {
    //given
    plate = createLicensePlateWithDefaultCountry(PLATE_NUMBER_FIRST, ENGINE_EURO_LEVEL_FIRST);
    //when
    plate = licensePlateRepository.save(plate);
    //then
    // First version number is  -- comment : if you want to comment something , include it into assert fail message
    assertEquals("version should be 1 for just created LicensePlate ", 1, plate.getVersion());
}

@Test
public void check_that_version_is_increased_when_changing_some_auditable_data() {
    //given
    plate = createLicensePlateWithDefaultCountry(PLATE_NUMBER_FIRST, ENGINE_EURO_LEVEL_FIRST);
    plate = licensePlateRepository.save(plate);
    //when
    setPlateEngineEuroLevelAndLicensePlate(PLATE_NUMBER_SECOND,ENGINE_EURO_LEVEL_SECOND);
    plate = licensePlateRepository.save(plate);
    //then
    assertEquals("version should be increased when Changing some auditable data",2, plate.getVersion());

    // Check if the entry in the database has updated data
    LicensePlate plateInDB = licensePlateRepository.findOne(plate.getId());
    assertNotNull(".. explanation..." , plateInDB);
    assertPlateNumberAndEngineEuroLevelAsInPlate(PLATE_NUMBER_SECOND , ENGINE_EURO_LEVEL_SECOND, plateInDB);
}

@Test
public void verify_revisions_after_two_changes() {
    //given
    plate = createLicensePlateWithDefaultCountry(PLATE_NUMBER_FIRST, ENGINE_EURO_LEVEL_FIRST);
    plate = licensePlateRepository.save(plate);
    //when
    setPlateEngineEuroLevelAndLicensePlate(PLATE_NUMBER_SECOND,ENGINE_EURO_LEVEL_SECOND);
    plate = licensePlateRepository.save(plate);
    //then
    Revisions<Integer, LicensePlate> revisions = licensePlateRepository.findRevisions(plate.getId());

    assertNotNull(".....something like : revisions should be found...." ,revisions);
    assertNotNull(".....something like : revisions.getContent should be found...." ,revisions.getContent());
    assertFalse(" should be present content for revisions " ,  revisions.getContent().isEmpty());
    assertEquals("I should have 2 revisions" ,2, revisions.getContent().size());

    //!!!! if you sure about order !!!!
    Revision<Integer, LicensePlate> revFirst = revisions.getContent().get(0);
    Revision<Integer, LicensePlate> revSecond = revisions.getContent().get(1);

    assertPlateNumberAndEngineEuroLevelAsInPlate(PLATE_NUMBER_FIRST, ENGINE_EURO_LEVEL_FIRST, revFirst.getEntity());
    assertPlateNumberAndEngineEuroLevelAsInPlate(PLATE_NUMBER_SECOND , ENGINE_EURO_LEVEL_SECOND, revSecond.getEntity());

}

private void assertPlateNumberAndEngineEuroLevelAsInPlate(String plateNumber , int engineEuroLevel , LicensePlate plate){
    assertEquals(engineEuroLevel, plate.getEngineEuroLevel());
    assertEquals(plateNumber , plate .getLicensePlate());
}

private LicensePlate createLicensePlateWithDefaultCountry(String plateNumber , int engineEuroLevel){
    LicensePlate plate = new LicensePlate();
    setPlateEngineEuroLevelAndLicensePlate(plateNumber , engineEuroLevel);
    plate.setCoutry(countryRepository.findFirstByOrderByIdAsc());
    return plate;
}

private void setPlateEngineEuroLevelAndLicensePlate(String plateNumber , int engineEuroLevel){
    plate.setEngineEuroLevel(engineEuroLevel);
    plate.setLicensePlate(plateNumber);
}
}