Java代码从JUnit调用PATCH方法

时间:2019-01-09 07:43:31

标签: spring-rest

我有一个简单的MyLibraryApplication,该代码具有调用POST(TransactionControllerImpl.issueBookToMember)和PATCH(TransactionControllerImpl.returnBookTransaction)方法的代码。我已经引用了网上的一些链接,并尽力编写代码来调用PATCH方法。该代码可以在TransactionControllerTest(testBookReturnUsingRestTemplate和testBookReturnUsingMockMvc方法)中找到。调用POST的代码可以正常工作,但是调用PATCH的代码却无法正常工作。控件永远不会到达TransactionControllerImpl内部的returnBookTransaction。

错误:无效的PATCH方法。

我正在寻找TransactionControllerTest.testBookReturnUsingRestTemplate和testBookReturnUsingMockMvc方法的代码段。有人可以帮助我将此代码设置为正确的形状吗?

package com.mycompany.techtrial;

import java.util.Map;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;

import com.mycompany.techtrial.Transaction;

public interface TransactionController {
    public ResponseEntity<Transaction> issueBookToMember(@RequestBody Map<String, String> params);
    public ResponseEntity<Transaction> returnBookTransaction(@PathVariable(name="transaction-id") Long transactionId);
}



/**
 * 
 */
package com.mycompany.techtrial;

import java.time.LocalDateTime;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;


@RestController
public class TransactionControllerImpl implements TransactionController{


  /*
   * PLEASE DO NOT CHANGE SIGNATURE OR METHOD TYPE OF END POINTS
   * Example Post Request :  { "book":"Java8 Primer","member":"Test 1" }
   */
  @PostMapping(path = "/api/transaction")
  public ResponseEntity<Transaction> issueBookToMember(@RequestBody Map<String, String> params){

    String book = params.get("book");
    String member = params.get("member");
    Transaction transaction = new Transaction();
    transaction.setId(1L);
    transaction.setBook(book);
    transaction.setMember(member);
    transaction.setDateOfIssue(LocalDateTime.now());
    transaction.setDateOfReturn(Transaction.getDefaultReturnDate());
    return ResponseEntity.ok().body(transaction);
  }
  /*
   * PLEASE DO NOT CHANGE SIGNATURE OR METHOD TYPE OF END POINTS
   */
  @PatchMapping(path= "/api/transaction/{transaction-id}/return")
  public ResponseEntity<Transaction> returnBookTransaction(@PathVariable(name="transaction-id") Long transactionId){

        String book = "Java8 Primer";
        String member = "Test 1";
        Transaction transaction = new Transaction();
        transaction.setId(1L);
        transaction.setBook(book);
        transaction.setMember(member);
        transaction.setDateOfIssue(LocalDateTime.now().minusDays(10));
        transaction.setDateOfReturn(LocalDateTime.now());
        return ResponseEntity.ok().body(transaction);   

  }

}



package com.mycompany.techtrial;

import java.util.HashMap;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;


@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class TransactionControllerTest {

  MockMvc mockMvc;

  @Mock
  private TransactionController transactionController;

  @Autowired
  private TestRestTemplate template;

  @Before
  public void setup() throws Exception {
    mockMvc = MockMvcBuilders.standaloneSetup(transactionController).build();
  }


  @Test
  public void testBookIssue() throws Exception {
    HttpEntity<Object> transaction = getHttpEntity(
        "{\"book\": \"Java8 Primer\", \"member\": \"Test 1\" }");

    ResponseEntity<Transaction> response = template.postForEntity(
        "/api/transaction", transaction, Transaction.class);

    Assert.assertEquals("Java8 Primer", response.getBody().getBook());
    Assert.assertEquals("Test 1", response.getBody().getMember());
    Assert.assertEquals(200,response.getStatusCode().value());

  }

  @Test
  public void testBookReturnUsingRestTemplate() throws Exception {
    Long transactionId = new Long(1);
    HashMap<String,Long> uriVariables = new HashMap<String,Long>();
    uriVariables.put("transaction-id", transactionId);

    Transaction transaction = template.patchForObject(
            "/api/transaction/{transaction-id}/return",null, Transaction.class, uriVariables);

    Assert.assertEquals(new Long(1), transaction.getId());
    //Assert.assertEquals(200,response.getStatusCode().value());

  }


  @Test
  public void testBookReturnUsingMockMvc() throws Exception {
    Long transactionId = new Long(1);

    HashMap<String,Long> uriVariables = new HashMap<String,Long>();
    uriVariables.put("transaction-id", transactionId);
    ResultActions obj = mockMvc.perform( MockMvcRequestBuilders
              .patch("/api/transaction/{transaction-id}/return",transactionId)
              .content("")
              .contentType(MediaType.APPLICATION_JSON)
              .accept(MediaType.APPLICATION_JSON));

    System.out.println(obj.getClass());
    HttpStatus status = obj.andReturn().getModelAndView().getStatus();
    boolean success = status.is2xxSuccessful(); 
    System.out.println("success="+success);

    Assert.assertEquals(new Long(1), transactionId);
    //Assert.assertEquals(200,response.getStatusCode().value());

  }

  private HttpEntity<Object> getHttpEntity(Object body) {
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    return new HttpEntity<Object>(body, headers);
  }

}




package com.mycompany.techtrial;

import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;

public class Transaction implements Serializable {

  private static final long serialVersionUID = 8951221480021840448L;

  private static final LocalDateTime defaultReturnDate = LocalDateTime.of(LocalDate.of(2299, 12, 31), LocalTime.of(12, 0, 0));

  Long id;


  private String book;
  private String member;

    public String getBook() {
        return book;
    }

    public void setBook(String book) {
        this.book = book;
    }

    public String getMember() {
        return member;
    }

    public void setMember(String member) {
        this.member = member;
    }

//Date and time of issuance of this book
  LocalDateTime dateOfIssue;

  //Date and time of return of this book
  LocalDateTime dateOfReturn;

  public Long getId() {
    return id;
  }

  public void setId(Long id) {
    this.id = id;
  } 

  public LocalDateTime getDateOfIssue() {
    return dateOfIssue;
  }

  public void setDateOfIssue(LocalDateTime dateOfIssue) {
    this.dateOfIssue = dateOfIssue;
  }

  public LocalDateTime getDateOfReturn() {
    return dateOfReturn;
  }

  public void setDateOfReturn(LocalDateTime dateOfReturn) {
    this.dateOfReturn = dateOfReturn;
  }

  @Override
  public String toString() {
    return "Transaction [id=" + id + ", book=" + book + ", member=" + member + ", dateOfIssue=" + dateOfIssue + ", dateOfReturn=" + dateOfReturn + "]";
  }

  //@PrePersist
  void preInsert() {
     if (this.dateOfReturn == null)
         this.dateOfReturn = defaultReturnDate;
  }

  public static LocalDateTime getDefaultReturnDate() {
      return defaultReturnDate;
  }
}



package com.mycompany.techtrial;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class MyLibraryApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyLibraryApplication.class, args);
      }
}

Error shown in testBookReturnUsingRestTemplate

Error shown in testBookReturnUsingMock

1 个答案:

答案 0 :(得分:0)

RestTemplate默认的Http客户端似乎是一个已知问题。

RestTemplate bug

一种解决方法是使用RestTemplateBuilder.setRequestFactory中的apache httpcomponents httpclient库并将其在构造函​​数中传递给TestRestTemplate

之后,您可以在TestRestTemplate类上使用exchange方法并执行PATCH请求。

创建TestRestTemplate的示例代码:

Supplier<ClientHttpRequestFactory> supplier = () -> {
   return new HttpComponentsClientHttpRequestFactory();
};
restTemplateBuilder.requestFactory(supplier);
TestRestTemplate testRestTemplate = new TestRestTemplate(restTemplateBuilder);
testRestTemplate.exchange("/api/transaction/{transaction-id}/return",HttpMethod.PATCH,null,Transaction.class,uriVariables);