Spring,测试时的不同行为
Spring, different behaviour when testing
我正在试验 Spring Web 并测试 REST 控制器。
该应用程序基本上是一个可通过 Web 服务访问的游戏数据库。
当我启动它并使用 Postman 对其进行测试以添加游戏时,我得到了我正在寻找的行为。
但是,当我使用 SpringJUnit4ClassRunner 测试控制器时,似乎我要添加的游戏已经存在于数据库中,我无法添加它。
这是我的测试class:
@RunWith(SpringJUnit4ClassRunner.class)
@WebMvcTest(GameController.class)
public class GameControllerTest {
@MockBean
private IGameService gameService;
@Autowired
private MockMvc mockMvc;
@Test
public void postGameTest() throws Exception {
String mockGameJson = "{\"name\":\"Test Game\",\"description\":\"A test game.\"}";
//Create a post request with an accept header for application\json
RequestBuilder requestBuilder = MockMvcRequestBuilders
.post("/game/")
.accept(MediaType.APPLICATION_JSON).content(mockGameJson)
.contentType(MediaType.APPLICATION_JSON);
MvcResult result = mockMvc.perform(requestBuilder).andReturn();
MockHttpServletResponse response = result.getResponse();
//Assert that the return status is CREATED
assertEquals(HttpStatus.CREATED.value(), response.getStatus());
}
}
最后一行断言失败,因为状态是 http 409 冲突
我个人return在控制器中的状态:
@RestController
public class GameController {
@Autowired
private IGameService gameService;
@PostMapping("/game")
public ResponseEntity<String> addGame(@RequestBody Game game, UriComponentsBuilder builder) {
boolean flag = gameService.addGame(game);
if (!flag) return new ResponseEntity<>("Another game with this name already exists.", HttpStatus.CONFLICT);
HttpHeaders headers = new HttpHeaders();
headers.setLocation(builder.path("/game/{id}").buildAndExpand(game.getId()).toUri());
return new ResponseEntity<>(headers, HttpStatus.CREATED);
}
...
发生这种情况是没有意义的,因为我的数据库在测试开始时应该是空的,对吗?
这是相关服务:
@Service
public class GameService implements IGameService { //Service layer
@Autowired
private IGameDAO gameDAO;
@Override
public synchronized boolean addGame(Game game) {
if(gameDAO.gameExists(game.getName()))
return false;
else {
gameDAO.addGame(game);
return true;
}
}
...
DAO:
@Transactional
@Repository
public class GameDAO implements IGameDAO {
@PersistenceContext
private EntityManager entityManager;
@Override
public void addGame(Game game) {
entityManager.persist(game);
}
@Override
public boolean gameExists(String name) {
String jpql = "from Game as g WHERE g.name = ?0 ";
int count = entityManager.createQuery(jpql).setParameter(0, name).getResultList().size();
return count > 0;
} ...
这些是我的 build.gradle
中的依赖项
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'com.h2database:h2'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
我做错了什么?
解决了。
正如所评论的那样,最好独立测试这些层。
在这里,我试图测试我的控制器(网络)。该服务是模拟的,因此默认情况下,对应该 return 布尔值的方法的任何调用都会 return false.
我不得不将模拟服务设置为 return true 以充分测试 post 方法。像这样:
given(gameService.addGame(any())).willReturn(true);
我正在试验 Spring Web 并测试 REST 控制器。 该应用程序基本上是一个可通过 Web 服务访问的游戏数据库。
当我启动它并使用 Postman 对其进行测试以添加游戏时,我得到了我正在寻找的行为。 但是,当我使用 SpringJUnit4ClassRunner 测试控制器时,似乎我要添加的游戏已经存在于数据库中,我无法添加它。
这是我的测试class:
@RunWith(SpringJUnit4ClassRunner.class)
@WebMvcTest(GameController.class)
public class GameControllerTest {
@MockBean
private IGameService gameService;
@Autowired
private MockMvc mockMvc;
@Test
public void postGameTest() throws Exception {
String mockGameJson = "{\"name\":\"Test Game\",\"description\":\"A test game.\"}";
//Create a post request with an accept header for application\json
RequestBuilder requestBuilder = MockMvcRequestBuilders
.post("/game/")
.accept(MediaType.APPLICATION_JSON).content(mockGameJson)
.contentType(MediaType.APPLICATION_JSON);
MvcResult result = mockMvc.perform(requestBuilder).andReturn();
MockHttpServletResponse response = result.getResponse();
//Assert that the return status is CREATED
assertEquals(HttpStatus.CREATED.value(), response.getStatus());
}
}
最后一行断言失败,因为状态是 http 409 冲突
我个人return在控制器中的状态:
@RestController
public class GameController {
@Autowired
private IGameService gameService;
@PostMapping("/game")
public ResponseEntity<String> addGame(@RequestBody Game game, UriComponentsBuilder builder) {
boolean flag = gameService.addGame(game);
if (!flag) return new ResponseEntity<>("Another game with this name already exists.", HttpStatus.CONFLICT);
HttpHeaders headers = new HttpHeaders();
headers.setLocation(builder.path("/game/{id}").buildAndExpand(game.getId()).toUri());
return new ResponseEntity<>(headers, HttpStatus.CREATED);
}
...
发生这种情况是没有意义的,因为我的数据库在测试开始时应该是空的,对吗? 这是相关服务:
@Service
public class GameService implements IGameService { //Service layer
@Autowired
private IGameDAO gameDAO;
@Override
public synchronized boolean addGame(Game game) {
if(gameDAO.gameExists(game.getName()))
return false;
else {
gameDAO.addGame(game);
return true;
}
}
...
DAO:
@Transactional
@Repository
public class GameDAO implements IGameDAO {
@PersistenceContext
private EntityManager entityManager;
@Override
public void addGame(Game game) {
entityManager.persist(game);
}
@Override
public boolean gameExists(String name) {
String jpql = "from Game as g WHERE g.name = ?0 ";
int count = entityManager.createQuery(jpql).setParameter(0, name).getResultList().size();
return count > 0;
} ...
这些是我的 build.gradle
中的依赖项dependencies {
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'com.h2database:h2'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
我做错了什么?
解决了。 正如所评论的那样,最好独立测试这些层。 在这里,我试图测试我的控制器(网络)。该服务是模拟的,因此默认情况下,对应该 return 布尔值的方法的任何调用都会 return false.
我不得不将模拟服务设置为 return true 以充分测试 post 方法。像这样:
given(gameService.addGame(any())).willReturn(true);