2017-06-14 3 views
0

Ich schreibe REST API in Java und testen Sie mit Groovy und Spock.Groovy - Ambigous Handler Methoden

Methods in meinem Controller:

@GetMapping(value = "/{id}") 
    public ResponseEntity<ExampleObj> findById(@PathVariable Long id) { 
     final ExampleObj dto = service.findById(id); 
     if (dto != null) { 
      return new ResponseEntity<ExampleObj>(dto, HttpStatus.OK); 
     } 
     return new ResponseEntity<ExampleObj>(dto, HttpStatus.NOT_FOUND); 
    } 

@GetMapping(value = "/{name}") 
public ResponseEntity<ExampleObj> findByName(@PathVariable String name) { 
    final ExampleObj dto = service.findByName(name); 
    if (dto != null) { 
     return new ResponseEntity<ExampleObj>(dto, HttpStatus.OK); 
    } 
    return new ResponseEntity<ExampleObj>(dto, HttpStatus.NOT_FOUND); 
} 

Und mein Test in Spock:

@Unroll 
    'findByName test'() { 
     when: 
      def response = restTemplate.getForEntity(url, ExampleObj) 
     then: 
      response.getStatusCode() == statusCode 
     where: 
      url         | statusCode 
      '/endpoint/SomeName1'   | HttpStatus.OK 
      '/endpoint/NotExistingName' | HttpStatus.NOT_FOUND 

    } 

@Unroll 
    'findById test'() { 
     when: 
      def response = restTemplate.getForEntity(url, ExampleObj) 
     then: 
      response.getStatusCode() == statusCode 
     where: 
      url     | statusCode 
      '/endpoint/1' | HttpStatus.OK 
      '/endpoint/2' | HttpStatus.NOT_FOUND 

    } 

Und wenn ich laufe Test ich die folgende Ausnahme erhalten:

java.lang.IllegalStateException: Für den HTTP-Pfad 'http://localhost:35287/endpoint/SomeName1' wurden mehrdeutige Handlermethoden zugeordnet: {public org.springframework.http.ResponseEntity ExampleController.findByName (java.lang.String), öffentliche Organisation. springframework.http.ResponseEntity ExampleController.findById (java.lang.Long)}

+1

es kann einfach nicht entscheiden, welche Methode, da beide auf den gleichen Pfad verknüpft nennen '/' – daggett

+0

leid, dass ich eine Frage bearbeitet – user

+0

Nr. Das Problem ist in '@GetMapping (value ="/{id} ")' und '@GetMapping (value ="/{name} ")'. Es gibt keinen Unterschied in diesen URLs. zum Beispiel: '/ 111' - wie sollte das Mapping identifizieren, was'/{id} 'oder'/{name} 'heißt? – daggett

Antwort

1

Spring kann nicht zwischen "/ {id}" und "/ {name}" unterscheiden. Es ist wirklich mehrdeutig, denn auch wenn name ein String ist und id eine Zahl ist, kann der Name auch die Form "43" haben. Wenn Sie also "/ 43" aufrufen, kann es als Name interpretiert werden (String "43") und als Long (43).

können Sie verwenden stattdessen so etwas wie:

@GetMapping(value = "/") 
public ResponseEntity<ExampleObj> findByName(@RequestParam("name") String name) { 
... 
1

Wie andere gesagt haben, werden Sie irgendwie die URL unterscheiden müssen. ZB

@GetMapping(value = "/id/{id}") 
public ResponseEntity<ExampleObj> findById(@PathVariable Long id) { ... } 

@GetMapping(value = "/name/{name}") 
public ResponseEntity<ExampleObj> findByName(@PathVariable String name) { ... } 

Oder Sie könnten das Routing selbst tun. ZB:

@GetMapping(value = "/{value}") 
public ResponseEntity<ExampleObj> find(@PathVariable String value) { 
    try { 
     long id = Long.parseLong(value); 
     return findById(id); 
    } catch (NumberFormatException e) { 
     return findByName(value); 
    } 
} 
Verwandte Themen