Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/389.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 我可以在这个场景中编写任何有意义的单元测试吗?_Java_Unit Testing_Junit_Testability - Fatal编程技术网

Java 我可以在这个场景中编写任何有意义的单元测试吗?

Java 我可以在这个场景中编写任何有意义的单元测试吗?,java,unit-testing,junit,testability,Java,Unit Testing,Junit,Testability,我有这个实体- public class MerchantConfig { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private Long merchantId; private String configKey; private String configValue; .. } 目前,它在商户级别存储配置(密钥和值) 我们现在也需要在用户

我有这个实体-

public class MerchantConfig {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private Long merchantId;
    private String configKey;
    private String configValue;
    ..
}
目前,它在商户级别存储配置(密钥和值)

我们现在也需要在用户级别存储配置(用户到商家一对多映射)

我们将这两列添加到实体中-

private Long entityId;
private String entityType;
entityId现在将存储merchantId/UserId,entityType将用字符串值“merchantId”或“user\u id”指示相同的值

下面是一个现有的服务层方法-

public MerchantConfig enableSync(boolean isActive, Long merchantId,boolean isSync){
        MerchantConfig merchantConfig= merchantConfigRespository.findByMerchantIdAndConfigKey(merchantId,Constants.MerchantConfigKeys.SYNC_ENABLED.key);
        if(merchantConfig==null){
            merchantConfig = new MerchantConfig();
            merchantConfig.setMerchantId(merchantId);
            merchantConfig.setConfigKey(Constants.MerchantConfigKeys.SYNC_ENABLED.key);
        }
        if(isSync)
            merchantConfig.setConfigValue("1");
        else
            merchantConfig.setConfigValue("0");
        merchantConfig.setIsActive(isActive);
        return merchantConfigRespository.save(merchantConfig);
    }
这是它上面的控制器-

@PostMapping("/admin/enableSync")
public ResponseEntity<Object> enableSync(HttpServletRequest request, HttpServletResponse response,
                                                  @RequestParam("merchantId") Long merchantId,
                                                  @RequestParam("isValid") boolean isValid,
                                                  @RequestParam("isSync") boolean isSync) {
    if (isValid && isSync)
        LOGGER.info("enabling sync for merchant {}", merchantId);
    else
        LOGGER.info("disabling sync for merchant {}", merchantId);

    MerchantConfig merchantConfig = merchantConfigService.enableSync(isValid, merchantId, isSync);
    if(merchantConfig!=null)
        return new ResponseEntity<>(new ResponseDTO(Constants.API_RESPONSE_SUCCESS, merchantConfig, "success"),
                HttpStatus.OK);
    return new ResponseEntity<>(new ResponseDTO(Constants.API_RESPONSE_FAILURE, "unable to enable sync"),
            HttpStatus.OK);
}
我在服务层放了什么有用的单元测试用例

如果我要模拟存储库层响应,并验证服务方法返回的MerchantConfig实体与模拟的响应相同,这会不会是一种过分的做法

相反,我觉得测试db值更有用,方法是向db中输入一些已知的条目。例如,在这种情况下,当数据库中已经有一些商户级配置,并且要输入用户级配置时,用户级条目应该覆盖,因为配置程序正在尝试取消设置所有商户级配置

如果给定db中的商户级配置,当调用save config API端点以保存用户级配置时,测试商户级配置是否被标记为不活动是很有用的


顺便问一下,这些测试叫什么?请给出一些解决方案,因为我在这场辩论中挣扎了很长时间。每次我坐下来写传统的单元测试用例时,我花费了太多的时间,但仍然有一些东西出现了问题,单元测试无法涵盖这些问题。请提供一些全面的指南来编写这样的测试。

首先,感谢您的提问! 这是一个好问题,让我思考。现在关于答案

如果有任何科学证明是编写测试的唯一正确方法,我不知道。作为一名专业人士,你必须打个电话。如果我是你,我会考虑这些事情:

  • 为几行更改编写单元测试看起来确实有些过分。很容易想象一个人如何以30行单元测试结束,并通过模拟来测试几行更改。让它成为选项1
  • 另一方面,使用DB编写集成测试(为了测试起见,可能在内存中)现在看起来可能是一个简单的解决方案。让它成为选项2
选项1 我使用的经验法则是,如果某些东西可以通过单元测试进行测试,那么它应该通过单元测试进行测试,除非我有充分的理由不这么认为。这是我个人的选择,原因如下:

  • 速度。单元测试的运行和调试速度总是更快(即使它们的编写时间更长)
  • 粒度。通过单元测试,我几乎总是知道问题在哪里
选项2 现在,在我看来,使用集成测试而不是单元测试的唯一合法原因是,有些东西非常难/不可能进行测试。如果我完全确信这部分逻辑永远不会改变,我可能会在你的案例中选择这个,但我认为情况并非如此

现在我们可以想出选项3:它看起来确实像
enableSync
对许多事情都有作用(即创建/查找对象并切换同步标志)

如果将下面的代码提取到一个单独的方法中(例如,build
merchantConfig
):

MerchantConfig-MerchantConfig=
if(merchantConfig==null){
merchantConfig=新merchantConfig();
merchantConfig.setEntityId(merchantId);
merchantConfig.setEntityType(枚举MerchantConfigType.MERCHANT_ID.v);
merchantConfig.setConfigKey(常量.MerchantConfigKeys.SYNC_ENABLED.key);
}

这应该很容易进行单元测试,并且不需要DB交互或模拟。

首先,感谢您的提问! 这是一个好问题,让我思考。现在关于答案

如果有任何科学证明是编写测试的唯一正确方法,我不知道。作为一名专业人士,你必须打个电话。如果我是你,我会考虑这些事情:

  • 为几行更改编写单元测试看起来确实有些过分。很容易想象一个人如何以30行单元测试结束,并通过模拟来测试几行更改。让它成为选项1
  • 另一方面,使用DB编写集成测试(为了测试起见,可能在内存中)现在看起来可能是一个简单的解决方案。让它成为选项2
选项1 我使用的经验法则是,如果某些东西可以通过单元测试进行测试,那么它应该通过单元测试进行测试,除非我有充分的理由不这么认为。这是我个人的选择,原因如下:

  • 速度。单元测试的运行和调试速度总是更快(即使它们的编写时间更长)
  • 粒度。通过单元测试,我几乎总是知道问题在哪里
选项2 现在,在我看来,使用集成测试而不是单元测试的唯一合法原因是,有些东西非常难/不可能进行测试。如果我完全确信这部分逻辑永远不会改变,我可能会在你的案例中选择这个,但我认为情况并非如此

现在我们可以想出选项3:它看起来确实像
enableSync
对许多事情都有作用(即创建/查找对象并切换同步标志)

如果将下面的代码提取到一个单独的方法中(例如,build
merchantConfig
):

MerchantConfig-MerchantConfig=
if(merchantConfig==null){
merchantConfig=新merchantConfig();
merchantConfig.setEntityId(merchantId);
merchantConfig.setEntityType(枚举MerchantConfigType.MERCHANT_ID.v);
商品配置
public MerchantConfig enableSync(boolean isActive, Long merchantId,boolean isSync){
    MerchantConfig merchantConfig= merchantConfigRespository.findByEntityIdAndEntityTypeAndConfigKey(merchantId,Enum.MerchantConfigType.MERCHANT_ID.v,Constants.MerchantConfigKeys.SYNC_ENABLED.key);
    if(merchantConfig==null){
        merchantConfig = new MerchantConfig();
        merchantConfig.setEntityId(merchantId);
        merchantConfig.setEntityType(Enum.MerchantConfigType.MERCHANT_ID.v);
        merchantConfig.setConfigKey(Constants.MerchantConfigKeys.SYNC_ENABLED.key);
    }
    if(isSync)
        merchantConfig.setConfigValue("1");
    else
        merchantConfig.setConfigValue("0");
    merchantConfig.setIsActive(isActive);
    return merchantConfigRespository.save(merchantConfig);
}