Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.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 为更复杂的方法编写JUnit测试_Java_Unit Testing_Testing_Junit - Fatal编程技术网

Java 为更复杂的方法编写JUnit测试

Java 为更复杂的方法编写JUnit测试,java,unit-testing,testing,junit,Java,Unit Testing,Testing,Junit,我正在学习JUnit测试程序,并且已经阅读了我能找到的所有教程。我理解实现基本测试的概念,例如当一个方法接受两个输入并使用它们来计算返回值时。在这种情况下,编写一个断言预期返回值应该是什么的测试很简单 然而,当有一个更复杂的方法需要测试时,比如使用随机对象生成的数字,或者如果需要测试一个不返回值的方法,该怎么办 例如,我想为以下方法编写一个测试: // Requirement 9.5.0 public void firePhotonTorpedos(TrekGUI gui, Starship t

我正在学习JUnit测试程序,并且已经阅读了我能找到的所有教程。我理解实现基本测试的概念,例如当一个方法接受两个输入并使用它们来计算返回值时。在这种情况下,编写一个断言预期返回值应该是什么的测试很简单

然而,当有一个更复杂的方法需要测试时,比如使用随机对象生成的数字,或者如果需要测试一个不返回值的方法,该怎么办

例如,我想为以下方法编写一个测试:

// Requirement 9.5.0
public void firePhotonTorpedos(TrekGUI gui, Starship target, int score)
{
    // Requirement 9.5.1.1
    // Torpedoes can either hit or miss.
    Random rand = new Random();
    boolean hit = false;
    int isItAHit= rand.nextInt(10);;
    int damage = 0;


    //80 % chance of hitting target
    if(isItAHit < 8)
    {
        hit = true;
    }

    // if it was a hit, calculate damage
    if(hit)
    {
        //damage between 30 and 50
        damage = rand.nextInt(21) + 30;

        target.setHitPoints(target.getHitPoints() - damage);
    }

    this.setPhotonTorpedos(this.getPhotonTorpedos() - 1);
    // Requirement 5.4.1
    this.setEnergy(this.getEnergy() - 50);


    //if target hit but not destroyed, say so
    if(hit && target.getHitPoints() > 0)
    {
        gui.getBottomPanel().getConsole().append("\nVessel at " + target.getQuadrantLocation() + ", " + target.getSectorLocation() + " damaged.");
        gui.getBottomPanel().getConsole().append("\n" + damage + " units damage."); 
    }
    //if target destroyed, say so and remove its ship
    // Requirement 6.2.0
    else if(hit && target.getHitPoints() < 0)
    {
        //warship is gone, so set its contains field to false and remove its icon
        target.getSectorLocation().setContainsWarship(false);
        target.getSectorLocation().getSectorView().hideWarshipIcon();

        klingonsLeft = klingonsLeft - 1;

        gui.getBottomPanel().getConsole().append("\n" + damage + " units damage.");
        gui.getBottomPanel().getConsole().append("Vessel at " + target.getQuadrantLocation() + ", " + target.getSectorLocation() + " destroyed.");

        // Increase score (bonus depending on how much energy is left)
        int bonus = this.getEnergy()/20;
        score = score + (50 + bonus);
    }
    //if it was a miss, say so
    else
    {
        gui.getBottomPanel().getConsole().append("Torpedo missed.");
    }
}
//要求9.5.0
公共虚空火箭筒(TrekguiGUI,星际飞船目标,智力分数)
{
//要求9.5.1.1
//鱼雷可能命中或未命中。
Random rand=新的Random();
布尔命中=假;
int-isItAHit=rand.nextInt(10);;
int损害=0;
//80%的命中率
如果(isItAHit<8)
{
命中=真;
}
//如果是命中,计算伤害
如果(命中)
{
//30到50之间的损坏
损坏=兰特·耐克斯汀(21)+30;
target.setHitPoints(target.getHitPoints()-伤害);
}
this.setPhotonTorpedos(this.getPhotonTorpedos()-1);
//要求5.4.1
this.setEnergy(this.getEnergy()-50);
//如果目标命中但未被摧毁,请说明
if(命中目标(&target.getHitPoints()>0)
{
gui.getBottomPanel().getConsole().append(“\n在“+target.getQuadrantLocation()+”,“+target.getSectorLocation()+”损坏“);
gui.getBottomPanel().getConsole().append(“\n”+伤害+”单位伤害“);
}
//如果目标被摧毁,说出来并移除它的飞船
//要求6.2.0
else if(命中目标(&target.getHitPoints()<0)
{
//战舰消失了,所以将其包含字段设置为false并移除其图标
target.getSectorLocation().setContainsWarship(false);
target.getSectorLocation().getSectorView().hideWarshipIcon();
klingonsLeft=klingonsLeft-1;
gui.getBottomPanel().getConsole().append(“\n”+伤害+”单位伤害“);
gui.getBottomPanel().getConsole().append(“容器位于“+target.getQuadrantLocation()+”,“+target.getSectorLocation()+”销毁”);
//增加分数(奖金取决于剩余能量的多少)
int bonus=this.getEnergy()/20;
分数=分数+(50+奖金);
}
//如果是失误,就说出来
其他的
{
gui.getBottomPanel().getConsole().append(“鱼雷丢失”);
}
}
我将如何为此编写正式测试?因为我在代码中有三条谓词语句,所以我知道我应该有三条通过代码的独立路径:

发射鱼雷>命中(否)>结束

发射鱼雷>命中(是)>计算伤害>摧毁(否)>船只残骸>结束

发射鱼雷>命中(是)>计算伤害>摧毁(是)>船只消失>结束

因此,如果我想获得完整的路径覆盖,例如,我需要编写至少三个测试用例来表达这些条件。很容易看出这些值可能是什么。但是我如何使用它们来编写测试呢?例如,JUnit是否可以访问代码中的布尔命中值,以便在不使用随机数的情况下定义该值?我知道我可以一步一步地检查代码是否正常工作(我已经这样做了),但有人告诉我应该使用更正式的测试手段,比如JUnit

我希望这些问题有意义。我只是希望能够更好地了解这种测试是如何在真实场景中进行的

然而,当有一种更复杂的方法需要测试时,比如使用随机对象生成的数字时,我们该怎么办

您可以找到一种控制
随机性的方法。例如,您可以将其传递到方法中,并使用一个无参数重载,如果您确实想调用它,可以使用
new Random()
调用它

这样,您的测试可以通过他们想要的任何
随机
实例-例如,一个带有预设种子的实例,或者一个使用模拟框架允许您控制返回值的实例

或者如果需要测试一个不返回值的方法

你测试一下副作用。你的方法肯定有副作用,否则就毫无意义了。您只需要一种访问这些副作用的方法(例如,通过调用
target.getHitPoints()

现在,您的方法似乎有“模型”副作用和UI副作用……而且它也相当长。这两种副作用都会使测试变得困难。将代码拆分为更小、更集中的方法通常会使其更易于阅读和测试。在这方面,将UI与业务逻辑分离也会有所帮助

然而,当有一种更复杂的方法需要测试时,比如使用随机对象生成的数字时,我们该怎么办

您可以找到一种方法来控制该
随机
。例如,您可以将其传递到该方法中,并使用一个无参数重载,如果确实需要,可以使用
new Random()
调用它

这样,您的测试可以通过他们想要的任何
随机
实例-例如,一个带有预设种子的实例,或者一个使用模拟框架允许您控制返回值的实例

或者如果需要测试一个不返回值的方法

您可以测试副作用。您的方法必须有副作用,否则它毫无意义。您只需要一种访问这些副作用的方法(例如,通过调用
target.getHitPoints()

现在,您的方法似乎有“模型”副作用和UI副作用……而且它也相当长。这两种副作用都会使测试变得困难。将代码拆分为更小、更集中的方法通常会使其更易于阅读和测试。将UI与业务逻辑分离有助于提高测试效率