Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/398.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:JUnitTest,抛出两个异常的测试方法_Java_Exception_Junit_Junit4 - Fatal编程技术网

JAVA:JUnitTest,抛出两个异常的测试方法

JAVA:JUnitTest,抛出两个异常的测试方法,java,exception,junit,junit4,Java,Exception,Junit,Junit4,我正在测试一个抛出两个不同异常的方法。这是我的标题: @测试(预期值=A8InvalidInputException.class) public void testGuessCharacter()引发8InvalidInputException、8AlreadyGuessedException { ... } 正文有两个try/catch块(对SO的搜索结果是一篇帖子,上面说这就是测试抛出异常的方式),每个异常对应一个。在我看来,我应该把它分成两种测试方法,特别是因为我只能有一个预期属性。但

我正在测试一个抛出两个不同异常的方法。这是我的标题:

@测试(预期值=A8InvalidInputException.class)

public void testGuessCharacter()引发8InvalidInputException、8AlreadyGuessedException
{
...
}

正文有两个try/catch块(对SO的搜索结果是一篇帖子,上面说这就是测试抛出异常的方式),每个异常对应一个。在我看来,我应该把它分成两种测试方法,特别是因为我只能有一个预期属性。但是,当我这样做时,应该测试8InvalidPutException的方法需要对8AlreadyGueSedException进行try/catch,而应该测试8AlreadyGueSedException的方法需要对8InvalidPutException进行try/catch。我真的不知道如何写这个测试。这是我尝试测试的方法:

/**
 * This method returns whether a specified character exists in the keyPhrase field
 * @param guess  a character being checked for in the keyPhrase field
 * @return  returns whether a specified character exists in the keyPhrase field
 * @throws A8InvalidInputException  if a non-valid character is passed as input to this method
 * @throws A8AlreadyGuessedException  if a valid character which has already been guessed is passed as input to this method
 */
public boolean guessCharacter(char guess) throws A8InvalidInputException, A8AlreadyGuessedException
{
    if(isValidCharacter(guess))
    {
        guess = Character.toLowerCase(guess);

        if(guessedCharacters.contains(guess) )
        {
            throw new A8AlreadyGuessedException("" + guess);
        }
        else
        {
            guessedCharacters.add(guess);
            if(keyPhrase.contains("" + guess))
                return true;
            else
            {
                numberOfGuessesLeft--;
                return false;
            }
        }       
    }
    else
    {
        throw new A8InvalidInputException("" + guess);
    }
}

是的,您应该将其分解为两个单元测试。一个使用无效输入触发
A8InvalidInputException
,另一个使用“已猜测”输入触发
A8AlreadyGueseDexException

只需在throws子句中添加两个异常:

@Test (expected = A8InvalidCharacterException.class) 
public void testInvalidCharacterScenario() throws A8InvalidInputException, A8AlreadyGuessedException { ... }

@Test (expected = A8InvalidInputException.class) 
public void testInvalidInputScenario() throws A8InvalidInputException, A8AlreadyGuessedException { ... }

然后,如果一个测试抛出另一个异常(意外的异常),那么您的测试将自动失败。

一个方法在运行时只能抛出一个异常。这就是为什么只能有一个预期属性

您可能需要三个测试用例:一个是当方法抛出一个异常时,一个是当方法抛出另一个异常时,另一个是当方法根本不抛出任何异常时


不要在
@Test
方法中添加任何try/catch语句,只要声明它们抛出异常即可。

考虑一下,为了使编写测试更简单,将它们分为两个不同的部分—分别测试
isValidCharacter
和测试
guessCharacter

假设
isValidCharacter(guess)
在收到无效猜测时将失败,我认为在该方法中抛出
A8InvalidInputException
将是理想的

public boolean isValidCharacter(char guess) throws A8InvalidInputException {
    // have your logic to check the guess, and if it's invalid, throw
}
然后,您需要做的就是测试这个特定的方法,看看它是否会在虚假输入上抛出异常

@Test (expected = A8InvalidInputException.class)
public void testIsValidCharacterWithInvalidCharacter() {
    // write your test here.
}
接下来,您可以将方法更改为只关心
isValidCharacter
方法的快乐路径,因为如果不返回布尔值,则抛出了异常

最后,您将只关心
guessCharacter
测试是否抛出
A8AlreadyGueseDexception

@Test (expected = A8AlreadyGuessedException.class)
public void testGuessCharacterWithAlreadyGuessedValue() {
    // write your test here.
}

不管怎么说,这个方法太长了。戴夫,是我的导师提供的。不是我写的。除此之外,根据Java编码指南/风格指南,我认为30行是业界认可的最大值。“业界认可的最大值?”从未听说过这样的事情。更重要的是,它具有足够高的圈复杂度,让我紧张不安:条件嵌套太深,无法方便地进行推理,而且在不需要条件的地方存在嵌套。重复逻辑,因为当所有其他内容都需要字符串时,会有一个字符。简单的展平(粗略地)解决了这个问题。适当的重构使测试变得如此琐碎,以至于近乎有趣。好吧,测试是为了实践,所以它一点也不复杂。我有另一位讲师,他教我们在将输入作为论点传递之前验证输入。数据验证发生在哪里基本上是无关紧要的。但是你错了;该方法处于圈复杂度的上限(10是一个典型的默认最大值;我得到了~5左右的twitchy)。方法应该做一件事,并且完全做到。这种方法明显不止一件事,增加了认知负荷,却没有相应的好处。结果就更难测试了。Etienne,好吧,这是有道理的,但你说仅仅声明它们抛出异常是什么意思?这周我刚刚学习了junittes,所以这对我来说还不是很直观。谢谢。我的意思是put
在测试方法头中抛出一个8InvalidPutException,一个8AlreadyGueseDexException
,但我现在看到你做到了。那么,为什么你需要在身体中使用try/catch块呢?我看到了一个on,所以说try/catch块是实现这一点的方法。否则,我真的不知道如何编写测试。你链接的帖子是关于一个更复杂的情况。在您的情况下,您的测试方法中不需要(也不应该有)try/catch块。好的,根据我上面提交的内容,您能给我一个身体应该是什么样子的线索吗?Makoto,谢谢,但我无法更改源代码。我的教练提供了它。一、 同样,我也会在这里编写单独的方法(可能在将其作为参数传递之前测试有效性?),因为我认为一个方法只应该做一件事,但嘿,我是学生。我知道什么?方法可以做很多事情,但是当你在测试时,你只应该测试一件事。我仍然强烈认为,
isValidCharacter
应该抛出异常,因为它是代码中唯一负责断言无效输入的部分。同样,它是关于限制测试必须达到的表面积-它使测试编写工作更容易,并且生成的测试不那么脆弱。