端点和存储库的 spock 测试
spock testing of endpoint and repository
正在进行我的 Spring 2.67 和 Spock 2.1-groovy-3.0 测试。我有基本的测试工作,但现在尝试一些集成测试但没有成功。我有一个控制器:
private ApiService apiService;
@Autowired
public ApiController(ApiService apiService) {
this.apiService = apiService;
}
@GetMapping("api/{scannedId}")
@ResponseBody
public ResponseEntity getScannedId(@PathVariable String scannedId) {
try {
logger.info("ApiKey Controller received GET /api/" + scannedId);
ApiKey found = apiService.retrieveValidApiKey(scannedId);
...
}
...
api服务有:
private ApiRepository apiRepository;
@Autowired
public ApiService(ApiRepository apiRepository) {
this.apiRepository = apiRepository;
}
public ApiKey retrieveValidApiKey(String uuid) {
ApiKey anApi = apiRepository.getApiKeyByApiKey(uuid);
if (anApi == null) {
logger.info("ApiService.retrieveValidApiKey({}) failed to find a matching ApiKey", uuid);
return null;
}
我有一个 Spock 测试,它使用两个值对数据库进行播种,然后成功调用 /api 端点。我在测试中有代码确认插入了两个值,但是当调用实际的 ApiService class 时,找不到它们:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureTestDatabase
class ApiControllerTest extends Specification {
@Shared Logger logger = LoggerFactory.getLogger(this.getClass())
@Autowired
ApiController apiController
@Autowired
ApiRepository apiRepository
@Transactional
def "GET by scannedId using apikey #apiKey should be #resultCode"() {
given:
def foundList = apiRepository.findAll()
logger.info("{} apiKeys in repository", foundList.size())
for (int i = 0; i < foundList.size(); i++) {
logger.info("Found ApiKey #{} apiKey: {} & uuid: {}", i, foundList.get(i).apiKey, foundList.get(i).uuid)
}
when:
def foundListCount = apiRepository.getApiKeyByApiKey(apiKey)
logger.info("FoundList: {}", foundListCount)
ResponseEntity<ApiKey> result = restTemplate.getForEntity( "/api/{scannedId}", ApiKey.class, apiKeyValue1)
logger.info("TestRestTemplate returned apikey: {}", result)
then:
assert result.getStatusCode() == resultCode
where:
apiKey || resultCode
"testApiKey3" || HttpStatus.NOT_FOUND
apiKeyValue1 || HttpStatus.OK
apiKeyValue2 || HttpStatus.OK
}
def setup() {
def apiKey1 = new ApiKey(apiKey: apiKeyValue1, uuid: uuid1, beginDate: beginDate1, endDate: endDate1)
def apiKey2 = new ApiKey(apiKey: apiKeyValue2, uuid: uuid2, beginDate: beginDate2, endDate: endDate2)
apiRepository.saveAndFlush(apiKey1)
apiRepository.saveAndFlush(apiKey2)
}
当我 运行 测试时,测试方法中的记录器吐出所有持久值。但是测试失败了,因为 ApiService.getScannedId 失败了,因为它没有看到测试设置中保留的值。
我无法使用 @DataJpaTest,因为当时没有加载 ApplicationContext,因此端点失败。
我不确定为什么 Spock 会看到通过存储库保留的值,但 ApiService 却看不到。这是上下文问题吗?如果可能的话,我真的很想在没有模拟的情况下进行测试。
问题是您的测试用 @Transactional
注释,这意味着只有在该方法中 运行 的东西才能看到数据。您发送的其余请求将由另一个无权访问事务的线程处理,因此不会看到数据。
如果你想让它工作,你必须删除注释,但是你还必须在测试结束时手动清理插入的数据/cleanup()
,因为你不能'不依赖事务回滚
正在进行我的 Spring 2.67 和 Spock 2.1-groovy-3.0 测试。我有基本的测试工作,但现在尝试一些集成测试但没有成功。我有一个控制器:
private ApiService apiService;
@Autowired
public ApiController(ApiService apiService) {
this.apiService = apiService;
}
@GetMapping("api/{scannedId}")
@ResponseBody
public ResponseEntity getScannedId(@PathVariable String scannedId) {
try {
logger.info("ApiKey Controller received GET /api/" + scannedId);
ApiKey found = apiService.retrieveValidApiKey(scannedId);
...
}
...
api服务有:
private ApiRepository apiRepository;
@Autowired
public ApiService(ApiRepository apiRepository) {
this.apiRepository = apiRepository;
}
public ApiKey retrieveValidApiKey(String uuid) {
ApiKey anApi = apiRepository.getApiKeyByApiKey(uuid);
if (anApi == null) {
logger.info("ApiService.retrieveValidApiKey({}) failed to find a matching ApiKey", uuid);
return null;
}
我有一个 Spock 测试,它使用两个值对数据库进行播种,然后成功调用 /api 端点。我在测试中有代码确认插入了两个值,但是当调用实际的 ApiService class 时,找不到它们:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureTestDatabase
class ApiControllerTest extends Specification {
@Shared Logger logger = LoggerFactory.getLogger(this.getClass())
@Autowired
ApiController apiController
@Autowired
ApiRepository apiRepository
@Transactional
def "GET by scannedId using apikey #apiKey should be #resultCode"() {
given:
def foundList = apiRepository.findAll()
logger.info("{} apiKeys in repository", foundList.size())
for (int i = 0; i < foundList.size(); i++) {
logger.info("Found ApiKey #{} apiKey: {} & uuid: {}", i, foundList.get(i).apiKey, foundList.get(i).uuid)
}
when:
def foundListCount = apiRepository.getApiKeyByApiKey(apiKey)
logger.info("FoundList: {}", foundListCount)
ResponseEntity<ApiKey> result = restTemplate.getForEntity( "/api/{scannedId}", ApiKey.class, apiKeyValue1)
logger.info("TestRestTemplate returned apikey: {}", result)
then:
assert result.getStatusCode() == resultCode
where:
apiKey || resultCode
"testApiKey3" || HttpStatus.NOT_FOUND
apiKeyValue1 || HttpStatus.OK
apiKeyValue2 || HttpStatus.OK
}
def setup() {
def apiKey1 = new ApiKey(apiKey: apiKeyValue1, uuid: uuid1, beginDate: beginDate1, endDate: endDate1)
def apiKey2 = new ApiKey(apiKey: apiKeyValue2, uuid: uuid2, beginDate: beginDate2, endDate: endDate2)
apiRepository.saveAndFlush(apiKey1)
apiRepository.saveAndFlush(apiKey2)
}
当我 运行 测试时,测试方法中的记录器吐出所有持久值。但是测试失败了,因为 ApiService.getScannedId 失败了,因为它没有看到测试设置中保留的值。
我无法使用 @DataJpaTest,因为当时没有加载 ApplicationContext,因此端点失败。
我不确定为什么 Spock 会看到通过存储库保留的值,但 ApiService 却看不到。这是上下文问题吗?如果可能的话,我真的很想在没有模拟的情况下进行测试。
问题是您的测试用 @Transactional
注释,这意味着只有在该方法中 运行 的东西才能看到数据。您发送的其余请求将由另一个无权访问事务的线程处理,因此不会看到数据。
如果你想让它工作,你必须删除注释,但是你还必须在测试结束时手动清理插入的数据/cleanup()
,因为你不能'不依赖事务回滚