我有以下Spring代码可以通过Spock进行测试:
@Service
@RequiredArgsConstructor
public class MyService {
private final RestTemplateBuilder restTemplateBuilder;
// ...
public Path downloadFile(String url) {
try {
ResponseEntity<byte[]> response = buildRestTemplate().getForEntity(url, byte[].class);
File tempFileZip = File.createTempFile("myTempFile", ".zip");
FileUtils.writeByteArrayToFile(tempFileZip, response.getBody());
return tempFileZip.toPath();
} catch (Exception e) {
// ...
}
}
private RestTemplate buildRestTemplate() {
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
Proxy proxy = new Proxy(/*...*/);
requestFactory.setProxy(proxy);
return restTemplateBuilder.requestFactory(() -> requestFactory).build();
}
}
使用此代码下载文件。我的test / resources文件夹中有一个样本文件,我想将其用于存根下载过程的结果。这是我可以使用它的一种方法,对此我有一些疑问:
package de.scrum_master.stackoverflow.q59630155
class MySpec extends Specification {
RestTemplate restTemplate = Stub {
getForEntity(_, byte[].class) >>
ResponseEntity.ok(
Files.readAllBytes(
Paths.get(
getClass()
.getResource("/data/MySample/MySample.zip")
.toURI()
)
)
)
}
RestTemplateBuilder restTemplateBuilder = Stub()
def myService = new MyService(restTemplateBuilder)
def setup() {
with(restTemplateBuilder) {
requestFactory(_) >> restTemplateBuilder
build() >> restTemplate
}
}
def "downloadFile"() {
when:
def response = myService.downloadFile()
then:
// ...
cleanup:
Files.delete(response)
}
}
A)我想更好地理解为什么资源文件的路径通过调试器评估为... target / test-classes / data / ebaRegistrySample / ebaRegistrySample.zip而不是包含/ test / resources的内容。是因为专家?
编辑:在评论中已经回答,这是由于maven inded。
B)将RestTemplateBuilder插入setup()或测试中可以正常工作。也可以在其中或在按规范进行初始化时,将RestTemplate存入其中,也可以使用。但是,当我还在规范中的初始化时也对RestTemplateBuilder进行存根时:
package de.scrum_master.stackoverflow.q59630155
class MySpec extends Specification {
// ...
RestTemplateBuilder restTemplateBuilder = Stub {
requestFactory(_) >> restTemplateBuilder
build() >> restTemplate
}
// ...
}
我得到一个
java.lang.NullPointerException: null
我这样做时也会遇到同样的异常
build() >> null
我怀疑在Spec的初始化时对restTemplate和restTemplateBuilder进行存根会导致restTamplate尚未有值,而restTemplateBuilder尝试访问它。我认为在初始化时像这样链接存根似乎应该可以工作,因此可能是一个错误。
是错误,还是还有其他原因导致它不起作用?
编辑:当我在初始化之后分别对requestFactory方法进行存根时,它确实起作用。因此,这只是C案例的另一个错误。
C)初始化RestTemplateBuilder时通常无法正常工作。如果前一种情况导致异常,请将其放在setup()或测试中:
package de.scrum_master.stackoverflow.q59630155
class MySpec extends Specification {
def "downloadFile"() {
setup:
RestTemplate restTemplate = Stub {
getForEntity(_, byte[].class) >>
ResponseEntity.ok(
Files.readAllBytes(
Paths.get(
getClass()
.getResource("/data/MySample/MySample.zip")
.toURI()
)
)
)
}
RestTemplateBuilder restTemplateBuilder = Stub() {
requestFactory(_) >> restTemplateBuilder
build() >> restTemplate
}
def myService = new MyService(restTemplateBuilder)
// ...
}
}
实际上导致编译错误:
requestFactory(_) >> restTemplateBuilder
No candidates found for method call restTemplateBuilder
编辑:一位同事建议这样做实际上是有意的,因为它可以防止堆栈中不确定的递归内存分配。
是错误,还是有其他原因导致它不起作用?
再次查看您自己的代码:
RestTemplateBuilder restTemplateBuilder = Stub {
requestFactory(_) >> restTemplateBuilder
build() >> restTemplate
}
您正在尝试在创建restTemplateBuilder
存根对象之前对返回restTemplateBuilder
的方法进行存根,这是一个自引用,类似于编写String text = "xy" + text
。这也解释了为什么它分两步工作:首先创建存根实例,然后对引用先前创建的对象的方法进行存根。
没有错误。问题出在键盘前面。没有冒犯的意思,这在我之前也发生过。 ;-)