我正在使用Spring和MongoDb测试API Rest资源。 这是"链"从资源到文档的关系:
资源:
@RestController
@RequestMapping(CustomerResource.CUSTOMERS)
public class CustomerResource {
public static final String CUSTOMERS = "/customers";
public static final String CUSTOMER_ID = "/{id}";
@Autowired
private CustomerController customerController;
@PostMapping
public void createCustomer(@RequestBody CustomerDto customerDto) {
this.customerController.createCustomer(customerDto);
}
...
}
控制器:
@Controller
public class CustomerController {
private CustomerRepository customerRepository;
...
public void createCustomer(CustomerDto customerDto) {
Customer customer = new Customer(customerDto.getName(),
customerDto.getAddress());
this.customerRepository.save(customer);
}
...
}
dto:
public class CustomerDto {
private String name;
private String address;
private Date date;
public CustomerDto (String name, String address) {
this.name = name;
this.address = address;
}
public CustomerDto() {
}
...(getters & setters & toString())...
}
存储库:
public interface CustomerRepository extends MongoRepository<Customer, String> {
public List<Customer> findByName(String name);
public Customer findById(String id);
public List<Customer> findAll();
@Query("{$and:[{'name':?0},{'address':?1}]}")
Customer findByNameAndAddress(String name, String address);
}
文件:
@Document
public class Customer {
@Id
private String id;
private String name;
private String address;
private Date date;
public Customer (String name, String address) {
this();
this.name = name;
this.address = address;
this.date = new Date();
}
public Customer() {
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Date getDate() {
return date;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Customer other = (Customer) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
}
@Override
public String toString() {
return "Customer [id=" + id + ", name=" + name + ", address=" + address + ", date=" + date + "]";
}
}
但是在运行测试时,我得到了NullPointer异常,并且我不明白过程的哪一点是错误。
资源测试:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@TestPropertySource(locations = "classpath:test.properties")
public class CustomerResourceFunctionalTesting {
@Rule
public ExpectedException thrown = ExpectedException.none();
@Autowired
private RestService restService;
private CustomerDto customerDto;
@Before
public void before() {
this.customerDto = new CustomerDto("Mark", "Washington");
}
@Test
public void testCreateCustomer() {
restService.restBuilder().path(CustomerResource.CUSTOMERS).body(this.customerDto).post().build();
}
}
我认为这可能与未明确声明id字段有关,但是因为它将被&#34;实例化&#34;通过@Id注释,我不认为存在问题。
这是追踪:
org.springframework.web.client.HttpServerErrorException: 500
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:88)
at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:708)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:661)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:636)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:557)
at account.persistence.resources.RestBuilder.build(RestBuilder.java:191)
at account.persistence.resources.CustomerResourceFunctionalTesting.testCreateCustomer(CustomerResourceFunctionalTesting.java:37)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:239)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:538)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206)
但我认为控制台日志会更有用:
java.lang.NullPointerException: null
at account.persistence.controllers.CustomerController.createCustomer(CustomerController.java:36) ~[classes/:na]
at account.persistence.resources.CustomerResource.createCustomer(CustomerResource.java:36) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_144]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_144]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_144]
at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_144]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133) ~[spring-web-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:661) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) ~[tomcat-embed-websocket-8.5.27.jar:8.5.27]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:108) ~[spring-web-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) ~[spring-web-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) ~[spring-web-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.27.jar:8.5.27]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:504) [tomcat-embed-core-8.5.27.jar:8.5.27]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.27.jar:8.5.27]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81) [tomcat-embed-core-8.5.27.jar:8.5.27]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.27.jar:8.5.27]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.27.jar:8.5.27]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803) [tomcat-embed-core-8.5.27.jar:8.5.27]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.27.jar:8.5.27]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:790) [tomcat-embed-core-8.5.27.jar:8.5.27]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459) [tomcat-embed-core-8.5.27.jar:8.5.27]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.27.jar:8.5.27]
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [na:1.8.0_144]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [na:1.8.0_144]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.27.jar:8.5.27]
at java.lang.Thread.run(Unknown Source) [na:1.8.0_144]
修改:
这是RestBuilder(在resoure测试的同一个文件夹中):
public class RestBuilder<T> {
private static final String SERVER_URI_DEFAULT = "http://localhost";
private static final int PORT_DEFAULT = 8080;
private RestTemplate restTemplate = new RestTemplate();
private String serverUri;
private int port;
private String path;
private List<Object> expandList;
private Map<String, String> headerValues;
private List<MediaType> mediaTytes;
private String authorization = null;
private Object body = null;
private MultiValueMap<String, String> params;
private Class<T> clazz;
private HttpMethod method;
private boolean log;
public RestBuilder(String serverUri, int port) {
restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory()); // org.apache.httpcomponents.httpclient
this.serverUri = serverUri;
this.port = port;
this.path = "";
this.expandList = new ArrayList<>();
this.headerValues = new HashMap<>();
this.mediaTytes = new ArrayList<>();
this.params = new HttpHeaders();
this.log = false;
}
public RestBuilder() {
this(SERVER_URI_DEFAULT, PORT_DEFAULT);
}
public RestBuilder(int port) {
this(SERVER_URI_DEFAULT, port);
}
public RestBuilder(String serverUri) {
this(serverUri, PORT_DEFAULT);
}
public RestBuilder<T> clazz(Class<T> clazz) {
this.clazz = clazz;
return this;
}
public RestBuilder<T> port(int port) {
this.port = port;
return this;
}
public RestBuilder<T> serverUri(String serverUri) {
this.serverUri = serverUri;
return this;
}
public RestBuilder<T> path(String path) {
this.path = this.path + path;
return this;
}
public RestBuilder<T> expand(Object... values) {
for (Object value : values) {
this.expandList.add(value);
}
return this;
}
public RestBuilder<T> basicAuth(String token) {
return basicAuth(token, "");
}
public RestBuilder<T> basicAuth(String nick, String pass) {
String auth = nick + ":" + pass;
String encodedAuth = Base64.getEncoder().encodeToString(auth.getBytes(StandardCharsets.UTF_8));
String authHeader = "Basic " + encodedAuth;
this.authorization = authHeader;
return this;
}
public RestBuilder<T> param(String key, String value) {
this.params.add(key, value);
return this;
}
public RestBuilder<T> header(String key, String value) {
this.headerValues.put(key, value);
return this;
}
public RestBuilder<T> accept(MediaType mediaType) {
if (this.mediaTytes.isEmpty()) {
this.mediaTytes.add(MediaType.APPLICATION_JSON);
}
this.mediaTytes.add(mediaType);
return this;
}
public RestBuilder<T> body(Object body) {
this.body = body;
return this;
}
public RestBuilder<T> notError() {
restTemplate.setErrorHandler(new DefaultResponseErrorHandler() {
protected boolean hasError(HttpStatus statusCode) {
return false;
}
});
return this;
}
private HttpHeaders headers() {
HttpHeaders headers = new HttpHeaders();
for (String key : headerValues.keySet()) {
headers.set(key, headerValues.get(key));
}
if (authorization != null) {
headers.set("Authorization", authorization);
}
if (!this.mediaTytes.isEmpty()) {
headers.setAccept(this.mediaTytes);
}
return headers;
}
private URI uri() {
UriComponents uriComponents;
if (params.isEmpty()) {
uriComponents = UriComponentsBuilder.fromHttpUrl(serverUri + ":" + port + path).build();
} else {
uriComponents = UriComponentsBuilder.fromHttpUrl(serverUri + ":" + port + path).queryParams(params).build();
}
if (!expandList.isEmpty()) {
uriComponents = uriComponents.expand(expandList.toArray());
}
return uriComponents.encode().toUri();
}
public RestBuilder<T> log() {
this.log = true;
return this;
}
public T build() {
ResponseEntity<T> response;
if (log) {
Logger.getLogger(this.getClass()).info(method + " " + this.path + this.headers() + "{" + this.body + "}");
}
if (body != null && !method.equals(HttpMethod.GET)) {
response = restTemplate.exchange(this.uri(), method, new HttpEntity<Object>(body, this.headers()), clazz);
if (log) {
Logger.getLogger(this.getClass()).info(response.getStatusCode() + "==" + response.getHeaders());
}
return response.getBody();
} else {
response = restTemplate.exchange(this.uri(), method, new HttpEntity<Object>(this.headers()), clazz);
if (log) {
Logger.getLogger(this.getClass()).info(response.getStatusCode() + "==" + response.getHeaders());
}
return response.getBody();
}
}
public RestBuilder<T> post() {
this.method = HttpMethod.POST;
return this;
}
public RestBuilder<T> get() {
this.method = HttpMethod.GET;
return this;
}
public RestBuilder<T> put() {
this.method = HttpMethod.PUT;
return this;
}
public RestBuilder<T> patch() {
this.method = HttpMethod.PATCH;
return this;
}
public RestBuilder<T> delete() {
this.method = HttpMethod.DELETE;
return this;
}
}
RestService(与RestBuilder在同一个文件夹中):
@Service
public class RestService {
@Autowired
private Environment environment;
@Value("${server.contextPath}")
private String contextPath;
private int port() {
return Integer.parseInt(environment.getProperty("local.server.port"));
}
public <T> RestBuilder<T> restBuilder(RestBuilder<T> restBuilder) {
restBuilder.port(this.port());
restBuilder.path(contextPath);
return restBuilder;
}
public RestBuilder<Object> restBuilder() {
RestBuilder<Object> restBuilder = new RestBuilder<>(this.port());
restBuilder.path(contextPath);
return restBuilder;
}
}
编辑2 :
作为替代方案,我尝试了另一种方法,因为我在Resource Access Exception中通过不使用RestService而不是修改测试和restbuilder来解释,但是在访问资源时我得到了一个异常。 / p>
答案 0 :(得分:0)
尝试在@Autowired
CustomerController
注释
@Autowired
private CustomerRepository customerRepository;
可能原因NullPointerException
是存储库没有正确注入。