2017-04-27 117 views
3

我試圖使用Spring Boot Test進行簡單的集成測試,以測試e2e用例。我的測試不起作用,因爲我'不能使資源庫保存的數據,我想我和春天有個上下文的問題...春季開機測試@Transactional未保存

這是我的實體:

@Entity 
@Getter 
@Setter 
@NoArgsConstructor 
@AllArgsConstructor 
public class Person { 
    @Id 
    private int id; 
    private String name; 
} 

這是人庫:

@Repository 
public interface PersonRepository extends JpaRepository<Person, Integer> { 
} 

的人服務:

@Service 
public class PersonService { 

    @Autowired 
    private PersonRepository repository; 

    public Person createPerson(int id,String name) { 
     return repository.save(new Person(id, name)); 
    } 

    public List<Person> getPersons() { 
     return repository.findAll(); 
    } 
} 

的人控制器:

@RequestMapping 
@RestController 
public class PersonController { 

    @Autowired 
    private PersonService personService; 

    @RequestMapping("/persons") 
    public List<Person> getPersons() { 
     return personService.getPersons(); 
    } 

}

主應用程序類:

@SpringBootApplication 
public class BootIntegrationTestApplication { 

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

的application.properties文件:

spring.datasource.url= jdbc:mysql://localhost:3306/test 
spring.datasource.username=root 
spring.datasource.password=password 
spring.jpa.hibernate.ddl-auto=create 
spring.jpa.show-sql=true 

和測試:

@RunWith(SpringRunner.class) 
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) 
public class BootIntegrationTestApplicationTests { 

    @Autowired 
    private PersonService personService; 
    @Autowired 
    private TestRestTemplate restTemplate; 

    @Test 
    @Transactional 
    public void contextLoads() { 
     Person person = personService.createPerson(1, "person1"); 
     Assert.assertNotNull(person); 

     ResponseEntity<Person[]> persons = restTemplate.getForEntity("/persons", Person[].class); 
    } 
} 

測試不起作用,因爲服務不保存Person實體.... 預先感謝

+3

那當然不是......你的測試是事務性的,所以事務包裝你的測試方法。所以之後會回滾(並且您的服務參與了該交易)。即使你使用'flush'也不行,因爲你正在使用rest來訪問會打開一個新事務的應用程序。使這項工作的唯一方法是使測試不是事務性的。 –

+0

你可以嘗試拆分你的測試。創建私有方法來保存具有事務註釋的人並從測試方法中調用它。 – kimy82

+0

正如@ M.Deinum所說,事務在您的測試中回滾,並且您看不到任何更改。嘗試在測試中添加'@Commit'或@Rollback(false)。 – dev4Fun

回答

1

感謝M. Deinum,我想我明白了, 所以最好是分開測試的邏輯成兩個試驗中,先將測試只是該服務(所以這一個可以是事務性)和所述第二控制器:

測試1:

@Test 
@Transactional 
public void testServiceSaveAndRead() { 
    personService.createPerson(1, "person1"); 
    Assert.assertTrue(personService.getPersons().size() == 1); 
} 

試驗2:

@MockBean 
private PersonService personService; 

@Before 
public void setUp() { 
    //mock the service 
    given(personService.getPersons()) 
      .willReturn(Collections.singletonList(new Person(1, "p1"))); 
} 

@Test 
public void testController() { 
    ResponseEntity<Person[]> persons = restTemplate.getForEntity("/persons", Person[].class); 
    Assert.assertTrue(persons.getBody()!=null && persons.getBody().length == 1); 
} 

希望它能夠幫助別人一天......感謝大家

0
@RunWith(SpringJUnit4ClassRunner.class) 
@SpringApplicationConfiguration(classes = Application.class) 

public class SmokeTest { 

    @Rollback(false) //This is key to avoid rollback. 
    @Test 
    public void contexLoads() throws Exception { 
     System.out.println("Hiren"); 

     System.out.println("started"); 
     _userDAO.save(new User("tyx", "[email protected]")); 
    } 

    @Autowired 
    UserController userController; 

    @Autowired 
    UserDao _userDAO; 
} 

參考@Rollback(假)是關鍵,以避免回滾。