@Transcational测试类影响事务性服务层的工作方式是什么?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (3)
  • 关注 (0)
  • 查看 (157)

我正在为我的Springboot应用程序REST控制器编写集成测试。

当我用@Transactional它不像预期的那样工作,当我删除注释时,它传递得很好。

  1. 使用@Transactional在测试类上意味着绝对没有任何东西被写入数据库?他们做的工作差不多是一样的。它们是写/更新/读的,但是这个测试测试一个删除端点。
  2. 如果用@Transaction注释测试类意味着没有对数据持久性的控制,那么人们为什么还要在测试中使用它呢?我将实体管理器注入测试类并调用flushclear,这没什么用。
  3. 即使数据没有写入数据库,它们也会被持久化,对吗?不调用repository.delete应该从持久性上下文中删除该项吗?
  4. 不影响db(DELETE)的代码位于服务层。我正在测试的是从Controller内部调用的,而不是测试类。我期望它能够工作,而不管测试类是用@Transacational或者不是。

服务层是@Transactional

这是在服务层,并由控制器调用。它不在测试中称为表单。

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

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

@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");
}

REST控制器的代码:

/*
 * 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());
}
提问于
用户回答回答于

需要重新考虑您的测试方法,并定义每组测试的测试范围。然后,根据这些作用域,可以定义一个策略,说明如何在每个作用域中隔离测试。然后,对于每个测试运行,应用适当的策略。

热门问答

腾讯云GPU服务器不能联外网吗?

小爱同学

腾讯云 · 技术支持 (已认证)

推荐
腾讯云GPU服务器可连外网,GPU 云服务器提供和标准CVM 云服务器一致的方便快捷的管理方式。 图片.png GPU云服务器作为CVM云服务器的一类特殊实例,购买、 操作、维护等方式与CVM云服务器一致 图片.png GPU 云服务器(GPU Cloud Computin...... 展开详请

win服务器怎么给文件夹配置755权限?

推荐
下面以腾讯云win服务器(Windows Server 2016 数据中心版 64位中文版)为文件夹配置755权限为例 1.右击【属性】 图片.png 2 .选择【安全】- 【编辑】 图片.png 3. 可对当前文件进行755权限配置 图片.png 要修改某个文件的权...... 展开详请

腾讯云sdk 兼容JDK6?

推荐

如果你说的是https://cloud.tencent.com/document/sdk/Java的话,jdk最低版本是1.7,不支持1.6

android 离线推送 为什么setOfflinePushListener不回调?

嗨喽你好摩羯座
推荐
您好,使用云通信 IM SDK 的通知栏提醒,建议参考:https://cloud.tencent.com/document/product/269/9234 中的描述来操作,通知栏提醒的内容由类 TIMOfflinePushNotification 来定义,可以通过这个类对外...... 展开详请

为什么cmq的topic配置订阅者为queue,向topic发送消息无法到达queue?

是的, 向topic发送消息应该会立即投递到订阅者。您可以检查您配置的队列名称是否正确且是真实存在的队列。如还不能解决您的问题,您可以点击控制台右上角的“工单”,进行问题进一步的排查,腾讯云会有专业的售后24小时为您服务。

脏字过滤只支持 TIMTextElem 消息,对自定义消息无效,请问有接口可以主动检查吗?

学生路人
推荐
您好,脏字检查的内容包括单聊和群组消息(只检查文本消息 TIMTextElem,不支持对自定义消息 TIMCustomElem 的过滤)、群名片、群组资料(群名称、群简介、群公告)用户资料和好友关系链中 bytes 类型的数据(如昵称、好友备注和好友分组等)。目前没有这样的接口喔...... 展开详请

所属标签

扫码关注云+社区