gpt4 book ai didi

java - @Transcational 测试类影响事务服务层的工作方式

转载 作者:IT老高 更新时间:2023-10-28 21:02:14 27 4
gpt4 key购买 nike

我正在为我的 Spring Boot 应用程序 Rest Controller 编写集成测试。

当我使用 @Transactional 注释测试类时,它无法按预期工作,而当我删除注释时,它会正常通过。

  1. 在测试类上使用 @Transactional 是否意味着绝对什么都没有写入数据库?我的其他测试工作正常!他们或多或少做同样的工作。他们写/更新/读但是这个test 测试删除端点。

  2. 如果使用 @Transactional 注释测试类意味着无法控制数据持久性,为什么人们甚至在测试中使用它?我将实体管理器注入(inject)到测试类中并调用了 flushclear,它没有帮助。

  3. 即使数据没有写入数据库,它们也会被持久化,对吧?不调用 repository.delete 应该从持久性上下文中删除该项目吗?

  4. 不影响db(删除)的代码位于Service层。它是从我正在测试的 Controller 中调用的,而不是测试类。无论测试类是否用 @Transacational 注释,我都希望它能够工作。

注意服务层是@Transactional

这是在服务层,由 Controller 调用。在测试中不叫表单。

public void delete(long groupId, String username) {
Group group = this.loadById(groupId);
User user = userService.loadByUsername(username);
groupRepository.delete(groupId);
}

编辑 1

测试失败的代码:

/*
* Deleting a group shouldn't delete the members of that group
*/
@Test
public void testDeleteGroupWithMembers() throws Exception {
Principal mockPrincipal = Mockito.mock(Principal.class);
Mockito.when(mockPrincipal.getName()).thenReturn(DUMMY_USERNAME);

User admin = userTestingUtil.createUser(DUMMY_USERNAME, DUMMY_USER_NAME, null, null);
Group group = groupTestingUtil.createGroup(DUMMY_GROUP_NAME, DUMMY_GROUP_DESCRIPTION, DUMMY_IMAGE_ID, admin);

User member = userTestingUtil.createUser("test1@test.test", "testUser1" , null, null);
group.addMember(member);

RequestBuilder requestBuilder = MockMvcRequestBuilders
.delete(GROUP_ENDPOINT_URL + group.getId())
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
.principal(mockPrincipal);

MvcResult result = mockMvc.perform(requestBuilder).andReturn();
MockHttpServletResponse response = result.getResponse();
int status = response.getStatus();
String content = response.getContentAsString();
Assert.assertEquals("wrong response status", 200, status);
Assert.assertEquals("wrong response content", "", content);
//This test fails, as the group is not yet deleted from the repo
Assert.assertEquals("there should be no group left", 0, Lists.newArrayList(groupRepository.findAll()).size());
Assert.assertEquals("wrong number of users exist", 2, Lists.newArrayList(userRepository.findAll()).size());
Assert.assertTrue("admin shouldn't get deleted when deleting a group", userRepository.findById(admin.getId()) != null);
Assert.assertTrue("group members shouldn't get deleted when deleting a group", userRepository.findById(member.getId()) != null);
}

在同一测试类中工作的测试代码:

@Test
public void testCreateGroup() throws Exception {
Principal mockPrincipal = Mockito.mock(Principal.class);
Mockito.when(mockPrincipal.getName()).thenReturn(DUMMY_USERNAME);

User user = userTestingUtil.createUser(DUMMY_USERNAME, DUMMY_USER_NAME, null, null);

JSONObject jo = new JSONObject();
jo.put(NAME_FIELD_NAME, DUMMY_GROUP_NAME);
jo.put(DESCRIPTION_FIELD_NAME, DUMMY_GROUP_DESCRIPTION);
jo.put(IMAGE_FIELD_NAME, DUMMY_IMAGE);
String testGroupJson = jo.toString();

RequestBuilder requestBuilder = MockMvcRequestBuilders
.post(GROUP_ENDPOINT_URL).content(testGroupJson)
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
.principal(mockPrincipal);

MvcResult result = mockMvc.perform(requestBuilder).andReturn();
MockHttpServletResponse response = result.getResponse();
int status = response.getStatus();
String content = response.getContentAsString();

List<Group> createdGroups = Lists.newArrayList(groupRepository.findAll());
Group createdGroup = createdGroups.get(0);

Assert.assertEquals("wrong response status", 200, status);
Assert.assertEquals("wrong response content", "", content);
Assert.assertEquals("wrong number of groups created", 1, createdGroups.size());
Assert.assertEquals("wrong group name", DUMMY_GROUP_NAME, createdGroup.getName());
Assert.assertEquals("wrong group description", DUMMY_GROUP_DESCRIPTION, createdGroup.getDescription());
Assert.assertEquals("wrong admin is assigned to the group", user.getId(), createdGroup.getAdmin().getId());
List<Group> groups = userTestingUtil.getOwnedGroups(user.getId());
Assert.assertEquals("wrong number of groups created for the admin", 1, groups.size());
Assert.assertEquals("wrong group is assigned to the admin", user.getOwnedGroups().get(0).getId(), createdGroup.getAdmin().getId());
Assert.assertTrue("image file was not created", CommonUtils.getImageFile(createdGroup.getImageId()).exists());
}

GroupService 中的创建和删除方法:

public void create(String groupName, String description, String image, String username) throws IOException {
User user = userService.loadByUsername(username);
Group group = new Group();
group.setAdmin(user);
group.setName(groupName);
group.setDescription(description);
String imageId = CommonUtils.decodeBase64AndSaveImage(image);
if (imageId != null) {
group.setImageId(imageId);
}
user.addOwnedGroup(group);
groupRepository.save(group);
logger.debug("Group with name " + group.getName() + " and id " + group.getId() + " was created");
}

public void delete(long groupId, String username) {
Group group = this.loadById(groupId);
User user = userService.loadByUsername(username);
validateAdminAccessToGroup(group, user);
groupRepository.delete(groupId);
logger.debug("Group with id " + groupId + " was deleted");
}

其余 Controller 的代码:

/*
* Create a group
*/
@RequestMapping(path = "", method = RequestMethod.POST)
public void create(@RequestBody PostGroupDto groupDto, Principal principal, BindingResult result) throws IOException {
createGroupDtoValidator.validate(groupDto, result);
if (result.hasErrors()) {
throw new ValidationException(result.getFieldError().getCode());
}
groupService.create(groupDto.getName(), groupDto.getDescription(), groupDto.getImage(), principal.getName());
}

/*
* Delete a group
*/
@RequestMapping(path = "/{groupId}", method = RequestMethod.DELETE)
public void delete(@PathVariable long groupId, Principal principal) {
groupService.delete(groupId, principal.getName());
}

编辑 2

我尝试删除 User 而不是 Group,但它也不起作用。在相同的方法(delete Group Service 层的方法)中创建一个组有效,但删除不行!

最佳答案

使用@Transactional注释测试时回滚。

  1. Does using @Transactional on a test class mean absolutely nothing gets written to the db ? My other tests work fine ! They do more or less the same job.

请发布您的其他测试以了解更多详细信息。

  1. If annotating a test class with @Transactional means there's no control on data persistence, why do people even use it on their tests ?

防止用测试数据填充数据库。

  1. Even if the data is not written to the db, they are persisted, right ? Doesn't calling repository.delete should delete that item from the persistence context ?

您在哪里检查项目是否已从持久性上下文中删除?

  1. The code that doesn't affect the db (delete) is located in the Service layer. It's called from within the Controller that I'm testing, not the test class. I expected it to work regardless of the fact that test class is annotated with @Transacational or not.

测试中的每个方法都使用 Spring 事务包装,因此在测试结束之前可能不会提交数据。

查看详细答案:

关于java - @Transcational 测试类影响事务服务层的工作方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45831099/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com