使用反射消隐字段

发布于 2024-08-18 16:54:10 字数 1171 浏览 4 评论 0原文

我正在编写一个 Junit 测试框架来测试 Web 服务。

要求输入值来自许多不同的源,例如早期的 Web 服务调用或类中的文字。

为了实现这一点,我有构造函数以不同的方式接受不同的输入;到目前为止一切都很简单。

问题是 Web 服务还需要使用完整的数据负载和仅强制字段的有效负载来执行。

我编写了一个注释 @Optional,而不是用 if 语句乱扔(在某些情况下很长)测试来决定是否设置值。

添加此注释会导致它被以下代码清空:

     /**
     * Find all of the fields annotated with optional and null them
     * @throws IllegalAccessException 
     * @throws IllegalArgumentException 
     */
    private void blankOptionalFields() throws IllegalAccessException{

        for(Field field: this.getClass().getDeclaredFields()){


            Annotation optionalAnnotation = field.getAnnotation(Optional.class);

            if(!(field.isSynthetic()) && optionalAnnotation instanceof Optional){

                field.setAccessible(true);
                try{
                    field.set(this, null);
                }
                catch(IllegalArgumentException e){
                    logger.debug("Tried to set a scalar field to null!", e);
                }
            }
        }
    }

所以有两件事:

1:虽然这有效,但不知何故感觉脆弱/危险,但必须有更好的方法吗? 2:如果这不是一种简单的方法,那么将标量值设置为适当值的最佳方法是什么?

I am writing a Junit test framework to test web services.

There is a requirement for the input values to come from many different sources, eg an earlier web service call or literals within the class.

To achieve this I have constructors that accept the different inputs in different ways; all simple so far.

The problem is the webservices also need to be exercised with a full data load and a mandatory fields only payload.

Rather then litter the (in some cases verrry long) tests with if statements deciding whether to set a value or not, I have written an annotation @Optional.

Adding this annotation causes it to be nulled by the following code:

     /**
     * Find all of the fields annotated with optional and null them
     * @throws IllegalAccessException 
     * @throws IllegalArgumentException 
     */
    private void blankOptionalFields() throws IllegalAccessException{

        for(Field field: this.getClass().getDeclaredFields()){


            Annotation optionalAnnotation = field.getAnnotation(Optional.class);

            if(!(field.isSynthetic()) && optionalAnnotation instanceof Optional){

                field.setAccessible(true);
                try{
                    field.set(this, null);
                }
                catch(IllegalArgumentException e){
                    logger.debug("Tried to set a scalar field to null!", e);
                }
            }
        }
    }

So two things:

1: Although this works it somehow feels fragile/dangerous, there must be a better approach?
2: If this is not a carzy approach, what is the best way to go about setting the scalar values to appropiate values?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

暮光沉寂 2024-08-25 16:54:10

定义一个仅包含一个清除可选属性的方法的接口怎么样?您可以测试一个对象来实现该接口并直接调用该方法。

这比尝试使用反射创建捕获所有情况更优雅地处理特定异常:

interface Blankable {

    /** @return true if all optional fields are successfully blanked. **/
    public boolean blankOptionalFields();
}

并使用类似:

if (obj implements Blankable) {

    if (!((Blankable) obj).blankOptionalFields()) {

        logger.debug("Could not blank optional fields for " + obj);
    }
}

How about defining an interface containing just the one method that blanks out optional attributes? You can test an object for implementing the interface and call the method directly.

This handles specific exceptions more elegantly than trying to create a catch all situation using reflection:

interface Blankable {

    /** @return true if all optional fields are successfully blanked. **/
    public boolean blankOptionalFields();
}

and use like:

if (obj implements Blankable) {

    if (!((Blankable) obj).blankOptionalFields()) {

        logger.debug("Could not blank optional fields for " + obj);
    }
}
凉薄对峙 2024-08-25 16:54:10

我会重构测试,将初始化代码从实际测试代码中分离出来。就此而言,您可以将实际的测试代码(调用 Web 服务的代码)放入在多个测试方法之间共享的方法中。

作为一个半相关的评论:我认为“单元”测试是独立执行服务方法,而“集成”测试则将其作为实际的 Web 服务来执行。

I would refactor the tests, splitting out the initialization code from the actual test code. For that matter, you could put the actual test code (the code that invokes the web service) into a method that is shared between multiple test methods.

As an semi-related comment: I would think of "unit" tests as exercising the service methods stand-alone, while "integration" tests would exercise it as an actual web service.

小忆控 2024-08-25 16:54:10

我不喜欢这种方法,因为您将测试代码与生产代码混合在一起。

如果您提前知道哪些字段是必需的,是否可以在设置它们时循环遍历这些字段,而无需使用复杂的 if 结构?

I'm not enamored with this approach because you're mixing test code in with your production code.

If you know which fields are mandatory ahead of time, is it possible to just loop through those fields at set them without a complicated if structure?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文