检查Junit中的2个预期值

时间:2011-01-12 10:51:11

标签: java junit


我有一个java程序,它针对2种不同的场景抛出了2个不同消息的异常,我希望Junit测试用例检查这两个消息是否相等。举个例子 -

public void amethod() {
           // do some processing
        if(scenario1 == true) {
            throw new MySystemException("An error occured due to case 1 being incorrect.");
        }
        else if(scenario2 == true) {
            throw new MySystemException("An error occured as case 2 could not be found");
        }
    }  

现在JUnit就像 -

public void testAMethod() {
    // do something
    assertEquals("Expected", "Actual");
}

据我了解,在上面的示例中,如果我使用Scenario1异常消息,则在Scenario2抛出异常时junit将失败,反之亦然。
我想知道在Junit中是否有任何其他方法可以使用这个test method并检查两个测试通过的消息?
OR这样的东西,如果可能的话,提供这些预期消息的“预期”值 我希望我的查询足够清楚。

谢谢

  

更新

对于延迟回复感到抱歉,已经遇到了其他一些紧急事项 谢谢大家提出的非常好的建议,它现在帮助我更好地理解了。
最后,为了保持相当简单,我决定实施Don Roby建议的类似解决方案。因此创建了一个新的测试类,看起来像 -

public void testAMethodScenario1() {
    // do the necessary
    assertEquals("Expected Exception Message 1", "Actual");
}

public void testAMethodScenario2() {
    // do the necessary
    assertEquals("Expected Exception Message 2", "Actual");
}  

再次感谢大家的回复。

8 个答案:

答案 0 :(得分:5)

我认为您需要手动捕获异常(针对每个方案)并单独检查消息:

try {
    // trigger scenario 1
    fail("An exception should have been thrown here !");
} catch (MySystemException e1) {
    assertEquals("Wrong error message", m1, e1.getMessage());
}

try {
    // trigger scenario 2
    fail("An exception should have been thrown here !");
} catch (MySystemException e2) {
    assertEquals("Wrong error message", m2, e2.getMessage());
}

当然,您可以将这些场景定义为枚举常量,并简单地遍历它们并在循环中检查它们中的每一个,因为“复制/粘贴设计模式”在上面的代码中非常明显。 :)

答案 1 :(得分:2)

您似乎在这里问两件事,如何测试异常以及如何断言值与两个可能的预期值匹配。

要测试异常,您可以使用JUnit4注释:

@Test(expected=MySystemException.class)
public void testException() {
   amethod();
}

或在测试中使用try-catch:

@Test
public void testException() {
   try {
      amethod();
      fail("MySystemException expected");
   }
   catch (MySystemException e) {
      // Success!
   }
}

如果你只有一条消息,在try-catch版本中你可以断言你在catch块中使用AssertEquals得到它。

最佳测试将针对您的两个方案进行单独测试,并期望正确的单个消息。事实上,更好的代码可能会对这两种情况有明显的例外。

但是,无论如何都需要一个比简单平等更复杂的断言,并且在Hamcrest匹配器中有一个优雅的解决方案。

在这种情况下使用它,您可以编写类似的内容(未经测试 - 完全不相信我的语法):

@Test
public void testException() {
   try {
      amethod();
      fail("MySystemException expected");
   }
   catch (MySystemException e) {
      String expectedMessage1 = "An error occured due to case 1 being incorrect.";
      String expectedMessage2 = "An error occured as case 2 could not be found";
      assertThat(e.getMessage(), 
                 anyOf(equalTo(expectedMessage1), equalTo(expectedMessage2)));
   }
}

答案 2 :(得分:1)

您能预测哪种情况会发生吗?如果是这样,Costi的答案是正确的。如果没有,因为有一些随机性或其他什么,你可以写:

@Test
public void testAmethodThrowsException() {
    try {
        amethod();
        fail("amethod() should have thrown an exception");
    }
    catch (MySystemException e) {
        String msg = e.getMessage();
        assertTrue("bad message: " + msg, msg.equals("An error occured due to case 1 being incorrect.") || msg.equals("An error occured as case 2 could not be found"));
    }
}

答案 3 :(得分:1)

方法抛出的声明的异常类型是其API的一部分。如果确实想要区分不同的故障模式,则应为每种故障模式声明不同的异常类型。

所以,像这样:

/**
 * Do something.
 * @throws MySystemException1 in case 1.
 * @throws MySystemException2 if Foo not found.
 */
public void amethod() {
   // do some processing 
   if(scenario1 == true) {
      throw new MySystemException1("Case 1.");
    }
    else if(scenario2 == true) {
        throw new MySystemException2("Foo not found");
    }
}  

答案 4 :(得分:0)

JUnit 4提供(Expected Exception.class)

@Test(expected= MySystemException.class) public void empty() { 
    // what ever you want
}

Google:有关更多信息的预期异常JUnit。

答案 5 :(得分:0)

JUnit4中的@Rule解决方案:

    public class ExceptionRule implements MethodRule {
        @Override
        public Statement apply(final Statement base, final FrameworkMethod method, Object target) {
            return new Statement() {
                @Override
                public void evaluate() throws Throwable {
                    try {
                        base.evaluate();
                        Assert.fail();
                    } catch (MySystemException e) {
                         if(scenario1)
                            assertEquals("Expected error message1", e1.getMessage();
                         if(scenario2)
                            assertEquals("Expected error message2",e1.getMessage();
                }
            }
        };    
    }
}

在您的测试用例中,使用规则:

 @Rule public ExceptionRule rule = new ExceptionRule();

答案 6 :(得分:0)

带有BDD

Catch Exception样式解决方案
@Test
public void testAMethodScenario1() {

    //given scenario 1

    when(foo).amethod();

    then(caughtException())
            .isInstanceOf(MySystemException.class)
            .hasMessage("An error occured due to case 1 being incorrect.");
}

@Test
public void testAMethodScenario2() {

    //given scenario 2

    when(foo).amethod();

    then(caughtException())
            .isInstanceOf(MySystemException.class)
            .hasMessage("An error occured as case 2 could not be found");
}

源代码

依赖关系

com.googlecode.catch-exception:catch-exception:1.2.0

答案 7 :(得分:0)

使用@Rule更好的解决方案,您还可以声明异常和期望消息。

@Rule
public ExpectedException expectedException = ExpectedException.none();

@Test
public void aMethod_Scenario1True_ThrowsException() {
    expectedException.expect(MySystemException.class);
    expectedExcepion.expectMessage("An error occured due to case 1 being incorrect.");

    //when().thenReturn(); 
    //handle the repositories, static methods and other sub methods, if needed

    amethod();
}

@Rule是编写异常的更优雅的方法。