java - 如何测试大型复杂代码?

标签 java unit-testing mocking

我有一个遗留代码,其中包含 8700 多行,每个方法平均长度约为 200-300 行。我想知道如何才能覆盖大部分代码,甚至获得成功结果的输出。

例如:

    public class Aviation implements FlightStruct, FlightSystem extends Vehicles {
    ...var decoration...
    ...override method definitions...

    public controls aviation(Flight request, Flight destination, Flight target) {

    FlightResponse flightResponse = new FlightResponse();

    flightResponse.speed = target.speed;
    angularVel.calculate(greatCircle.flightResponse.speed);
    _readVelData();
    if (vel.circular.velocity <= 10000) {
    for(countryName : country) {
    calculateArrivalTime();
    _readFuel();
    if(fuel.limit < pwi.percent*100) {
           createShortPathLandingPoint(Path newDestination, Register checkPoint);
       }
    }
}
    private eqiptment company(String name, Vendor vendor) {
    ....calculate equiptment stuff that calls bunch of private methods
    }

 ...alot more method here
    }
}

我想知道我应该如何对这些代码进行单元测试? 我尝试过 stub 数据,但内部方法太复杂,无法完成。通常一个方法会调用多层子方法。 例如.... Fuel 类调用 _readfuel,并在 _readfuel 中调用 destinationCheckPoint、flightWayPoint、flightSpeedCalc...然后在每个子方法中调用自己的子方法。 (例如,flightWaypoint 调用calculateWayPoint、angVelocity、speedLimit,...) 总的来说,我认为通过 stub 数据是不可能实现的,因为找到正确的数据很困难。 然后我的第二个选择是使用 Mockito 来模拟方法/类。这听起来更合理,但我再次遇到有多个私有(private)的子方法......并且mockito无法模拟私有(private)方法。然后我尝试使用 PowerMockito 来模拟它适用于几千行的私有(private)方法,结果如下:

while (!report.successful && !telCList.isEmpty()) {
...
report.wayPoint = update.assignWayPoint(wayPointList); //null point exception
...

其中更新为空,并且声明了它上面的几百行

 UpdateGateWay update = setDestinationWayPoint(distance, speed, altitude);

setDestinationWayPoint 是一个私有(private)方法,我使用 powerMockito 来模拟行为,我还返回了作为 stub 一部分的值。但是当它在下面被调用时它就会变成空。

此时我几乎放弃了。我想知道是否有更合理的方法来进行此类测试......

最佳答案

为您不理解的遗留代码库编写有值(value)的从头单元测试是一项艰巨的任务。特别是,如果代码很困惑;例如“每个方法平均长度约为 200-300 行”

问题是如何弄清楚方法>>应该<<以足够的准确度来编写单元测试。不幸的是,这通常需要更深入的洞察力,而不是简单地理解代码编写的行为方式。

这不是一项不可能完成的任务,但可能需要大量工作……具体取决于代码的内在复杂性、原始设计的质量、需求、问题领域等等。

一种可能的替代方案是将代码库视为黑匣子。不编写单元测试,而是根据一些“典型”场景编写系统测试;例如如果您从数据库状态 X 开始并提供输入 I,则期望输出 O 和新的数据库状态 X'。每次需要对旧代码库进行更改时,请添加新的系统测试。

<小时/>

I was wondering how am I able to cover most of those code even to get an output of a successful result.

我认为您在这里有一些误解。

  • 在进行单元测试时,覆盖的代码百分比并不像人们预期的那么重要。目标应该是覆盖可能存在错误的代码。

  • “成功的结果”是什么?单个方法调用?这假设您知道结果应该是什么。这可能很困难,特别是如果该方法具有您不知道或不理解的副作用。

<小时/>

最后一点是,某些代码本质上很难编写单元测试。通常,这些代码应该被重写。 8,700 行的代码库(实际上)并没有那么大,并且可以作为重写的候选者。 (您可以将现有代码视为“工作原型(prototype)”......在缺乏一组像样的功能需求的情况下。)

关于java - 如何测试大型复杂代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32149828/

相关文章:

java - AWS lambda JAVA : usage of external libraries

java - 如何区分类的两个实例

java - 动态创建一个对象,其中类名作为字符串给出

angularjs - 如何在 AngularJS 应用程序中模拟/ stub activate() 方法

c# - 通过 Entity Framework BeginTransaction

Javascript 测试 : Inconsistent number of tests

unit-testing - Azure cmdlet 调用上出现 Pester 模拟错误 PSInvalidCastException

java - Ren'py启动器: "Cannot find Java SE Runtime environment"

java - 如何模拟和测试这个内部静态类

java - 使用 Mockito 测试父类(super class)方法