我按照本教程(https://spring.io/guides/tutorials/react-and-spring-data-rest/#react-and-spring-data-rest-part-5)来试验Spring Data REST,我想用TestRestTemplate
测试CRUD。
以下是一个例子:
@Data
@Entity
public class Dojo {
private @Id @GeneratedValue Long id;
private String name;
private String location;
private Date created;
@OneToMany(mappedBy = "dojo")
@JsonIgnore
private List<Workshop> workshops;
private Dojo() {}
public Dojo(String name, String location) {
this.name = name;
this.location = location;
this.created = new Date();
this.workshops = new ArrayList<>();
}
//getters and setters ...
}
@Data
@Entity
public class Workshop {
private @Id @GeneratedValue Long id;
private String name;
@ManyToOne
private Dojo dojo;
private Workshop() {}
public Workshop(String name, Dojo dojo) {
this.name = name;
this.dojo = dojo;
}
}
所以,我在Dojo和amp;之间有一个双向的1:n关系。作坊。 @JsonIgnore注释用于避免与JSON Marshaller的无限循环。 存储库是标准的
public interface WorkshopRepository extends CrudRepository<Workshop, Long> {}
现在我的测试:我想更新研讨会。听起来不错,不起作用。
@Test
public void testUpdateWorkshop() throws Exception {
final String DOJO_NAME="My Dojo";
final String DOJO_LOCATION="Liege";
final String WORKSHOP_NAME="Stuff";
final String HOST_PORT="http://localhost:8080";
//creation of a dojo
final Dojo DOJO = dojoRep.save(new Dojo(DOJO_NAME,DOJO_LOCATION));
//creation of a workshop
Workshop workshop = workshopRep.save(new Workshop(WORKSHOP_NAME,DOJO));
String newValue = "After Test";
System.out.println("before update");
System.out.println(workshop.getName()+" == "+WORKSHOP_NAME);
Long oldID = workshop.getId();
//As you can see I didn't modify the workshop object
HttpEntity<Workshop> entity = new HttpEntity<Workshop>(workshop);
ResponseEntity<String> response = template.exchange(HOST_PORT+"/api/workshops/"+oldID, HttpMethod.PUT, entity, String.class, oldID);
assert response.getStatusCodeValue() == 200;
//re-Get the updated workshop
workshop = workshopRep.findOne(oldID);
System.out.println("after update");
System.out.println(workshop.getName()+" == "+WORKSHOP_NAME);
// as I didn't set the newValue, it must fail and workshop.getName() must stay equal to "Stuff".
Assert.assertEquals("Update does not work",newValue,workshop.getName());
}
我运行mvn clean test
和
before update
Stuff == Stuff
after update
My Dojo == Stuff
Failed tests:
WorkshopTests.testUpdateWorkshop:218 Update not work expected:<[After Test]> but was:<[My Dojo]>
所以基本上,我没有改变任何东西到我的对象但是
只是......为什么?
更多信息:
我也尝试使用mockMvc
代替TestRestTemplate
。
mockMvc.perform(put(HOST_PORT+"/api/workshops/"+oldID)
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(convertObjectToJsonBytes(workshop))
);
具有功能
private byte[] convertObjectToJsonBytes(Object object) throws IOException {
ObjectMapper mapper = new ObjectMapper();
System.out.println("log my face ");
System.out.println(mapper.writeValueAsString(object));
return mapper.writeValueAsBytes(object);
}
在更新之前,日志似乎正确地解析了我的对象......
{"id":1,"name":"Stuff","dojo":{"id":1,"name":"My Dojo","location":"Liege","created":1500799092330}}
但仍然不起作用:(
当我运行应用程序(mvn spring-boot:run)时,在localhost上获取GET:8080 / api / workshops / 1返回
{
"name" : "Stuff",
"_links" : {
"self" : {
"href" : "http://localhost-core:8080/api/workshops/1"
},
"workshop" : {
"href" : "http://localhost-core:8080/api/workshops/1"
},
"dojo" : {
"href" : "http://localhost-core:8080/api/workshops/1/dojo"
}
}
}
总结一下我的问题是:
感谢所有人,祝你有个美好的一天! : - )
答案 0 :(得分:0)
我认为这是因为你正在使用bidirectional one-to-many关联。在这种情况下,您必须自己提供实体的链接/取消链接。例如,在集合设置器中,如下所示:
@Data
@ToString(exclude = "slaves")
@Entity
public class Master {
@Id
@GeneratedValue
private Long id;
private String name;
@OneToMany(mappedBy = "master", cascade = {PERSIST, MERGE})
private List<Slave> slaves;
public void setSlaves(List<Slave> slaves) {
// link new slaves to this master
slaves.forEach(slave -> slave.setMaster(this));
// unlink prev slaves
if (this.slaves != null) this.slaves.forEach(slave -> slave.setMaster(null));
this.slaves = slaves;
}
}
@Data
@Entity
public class Slave {
@Id
@GeneratedValue
private Long id;
private String name;
@ManyToOne
private Master master;
}
然后您可以存储Slave
:
POST http://localhost:8080/api/slaves
{
"name": "slave1"
}
// the same for salve2, slave3, slave4
存储Master
:
POST http://localhost:8080/api/masters
{
"name": "master1",
"slaves": [
"http://localhost:8080/api/slaves/1",
"http://localhost:8080/api/slaves/2"
]
}
更新Master
:
PUT http://localhost:8080/api/masters/1
{
"name": "master1u",
"slaves": [
"http://localhost:8080/api/slaves/3",
"http://localhost:8080/api/slaves/4"
]
}
PUT http://localhost:8080/api/masters/2
{
"name": "master2"
}
或更新Slave
:
PUT http://localhost:8080/api/slaves/1
{
"name": "slave1u",
"master": "http://localhost:8080/api/masters/2"
}
PUT http://localhost:8080/api/slaves/2
{
"name": "slave2u",
"master": "http://localhost:8080/api/masters/2"
}
见工作example。
其他info