【Java单元测试】实习项目实际问题1--被测试函数中私有变量反射调用

问题简单描述

原Java类中函数调用其私有变量,写单元测试的时候没办法直接获取原Java类中私有变量

具体情况

1.原Java类代码(删除了与问题无关的代码,不影响具体描述)

public class ChargeBlock implements Parcelable {
    private int startHour1;//早些的时间段起始小时数,比如0

    @Override
    public String toString() {
        return "ChargeBlock{" +
                "startHour1=" + startHour1 +
                ", endHour1=" + endHour1 +
                ", startHour2=" + startHour2 +
                ", endHour2=" + endHour2 +
                '}';
    }
    public int getStartHour1() {
        return startHour1;
    }

    public void setStartHour1(int startHour1) {
        this.startHour1 = startHour1;
    }
}

2.问题具体分析
toString()函数中调用了ChargeBlock类中的私有变量startHour1,在一开始写testToString()函数的时候考虑的是直接在测试的时候调用对应的getxxx()函数,但是又想到此时getxxx()函数并没有被测试,不能默认getxxx()函数是不会出错的,所以选择反射调用获取私有变量,然后进行测试

3.具体测试代码

class ChargeBlockUT {
    private ChargeBlock target;
    
    //此处把获取私有变量提取出来作为一个单独的函数,可以降低代码重复性。
    //targetClassInstance:原Java类的对象(在调用fieldSet()函数前需要声明)
    //declaredField:被测试类中的私有变量的变量名
    //targetObject:是实际要设置字段值的对象实例
    //newValue:要设置到targetObject中指定字段的新值
    //声明了两个可能抛出的异常:NoSuchFieldException(如果指定的字段不存在)和IllegalAccessException(如果应用程序没有适当的访问权限来设置该字段的值)
    private void fieldSet(Object targetClassInstance, String declaredField, Object targetObject, Object newValue) throws NoSuchFieldException, IllegalAccessException {
        //获取被测试类中私有变量值
        Field field = targetClassInstance.getClass().getDeclaredField(declaredField);
        //确保可以访问私有字段,Java的反射API默认不允许访问私有字段,除非明确设置。
        field.setAccessible(true);
        //使用field.set(object, obj)将obj(新值)设置到object(目标对象)的declaredField(指定字段)中
        field.set(targetObject, newValue);
    }
    @BeforeAll
    public static void beforeAll() {
    ...
    }
    @AfterAll
    public static void afterAll() {
    ...
    }
    @BeforeEach
    public void beforeEach() {
        closeable = MockitoAnnotations.openMocks(this);
        target = new ChargeBlock();
    }

    @AfterEach
    public void afterEach() {
        try {
            closeable.close();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    @Test
    public void testToString() throws NoSuchFieldException, IllegalAccessException {
        //声明获得chargeBlock,以便调用fieldSet函数
        //PREPARE
        ChargeBlock chargeBlock = new ChargeBlock();
        fieldSet(chargeBlock, "startHour1", target, 1);
        fieldSet(chargeBlock, "endHour1", target, 2);
        fieldSet(chargeBlock, "startHour2", target, 3);
        fieldSet(chargeBlock, "endHour2", target, 4);

        //INVOKE
        String toString = target.toString();
        //ASSERT
        Assertions.assertEquals(toString, "ChargeBlock{startHour1=1, endHour1=2, startHour2=3, endHour2=4}");
    }
}

存在问题

在提交代码的时候,有AI审查结果(识别可改善项):使用反射操作私有字段: 代码中大量使用反射来访问和修改私有字段,这违反了封装性原则,可能导致安全问题。
但这个审查我忽略了,因为不这么处理的话需要将私有字段更改为受保护的,测试人员没有权限更改原Java类代码(或许也没有必要。。。)

技术细节

Java中反射的调用,此处只是调用私有变量,私有函数也可以调用,使用方法也很简单
反射原理理解比较难,但是实际写代码的时候很容易,使用Android studio写的很多时候都有提示。
以下是学习反射的时候看的文章(其实没怎么理解)

https://blog.csdn.net/weixin_74268571/article/details/131345164

小结

1.被测试类中私有变量在被测试函数中调用,测试函数应该如何去处理这些私有变量
2.测试函数处理私有变量的具体过程最好提出来作为一个函数,使用到反射调用的时候直接调用此函数,降低大块代码重复性(这是之后遇到的问题,刚写的时候遇到的被测试类中代码重复性不是很高。。)
3.写完所有测试任务后这确实是一个很小的问题,但是刚接触测试的时候也是思考了不少时间,在这里记录下自己测试实习的第一步。

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值