你能解释一下测试用例中的Exception是如何提供的吗?

时间:2013-10-21 10:20:08

标签: java unit-testing exception-handling junit

有关于在Junits中检查已处理异常的问题。我似乎在我的代码中完成了这个。其他人倾向于说这是不可能的,因为该方法不会引发异常。有人可以解释下面代码中发生的事情。

public class DatabaseConnector
{

private DBConnectionInfo dbObject;
private DBQueryStatements dbQueries;

void loadConnectionInfo()
{
    Properties databaseProperties = new Properties();
    try
    {
        databaseProperties.load(getClass().getClassLoader().getResourceAsStream("database.properties"));
        dbObject.setDatabaseURL(databaseProperties.getProperty("jdbc.url"));
        dbObject.setUserName(databaseProperties.getProperty("jdbc.username"));
        dbObject.setPassword(databaseProperties.getProperty("jdbc.password"));
        dbObject.setDriver(databaseProperties.getProperty("jdbc.driver"));
    } catch (IOException e)
    {

        Logger lgr = Logger.getLogger(PostgreLocationManager.class.getName());
        lgr.log(Level.SEVERE, e.getMessage(), e);
    }

}

public DBConnectionInfo connectionInit()
{

    loadConnectionInfo();

    try
    {
        Class.forName(dbObject.getDriver());
    } catch (Exception e)
    {
        Logger lgr = Logger.getLogger(PostgreLocationManager.class.getName());
        lgr.log(Level.SEVERE, e.getMessage(), e);
    }

    try
    {
        dbObject.setConnection(DriverManager.getConnection(dbObject.getDatabaseURL(), dbObject.getUserName(),
                dbObject.getPassword()));
    } catch (Exception e)
    {
        Logger lgr = Logger.getLogger(PostgreLocationManager.class.getName());
        lgr.log(Level.SEVERE, e.getMessage(), e);
    }
    return dbObject;
}
}

上述代码的测试用例。

public class DatabaseConnectorTest
{

DatabaseConnector dbConnector;
DBConnectionInfo dbModelObject;
DBQueryStatements dbQueries;

    @Before
    public void setUp() throws Exception
    {
        MockitoAnnotations.initMocks(this);
        dbModelObject = mock(DBConnectionInfo.class);
        dbQueries = mock(DBQueryStatements.class);    
        dbConnector = new DatabaseConnector(dbModelObject,dbQueries);
    }

@Test
public void testDriverFailure()
{
    when(dbModelObject.getDriver()).thenReturn("driver");
    when(dbModelObject.getDatabaseURL()).thenReturn("jdbc:postgresql://127.0.0.1:5432/testdb");
    when(dbModelObject.getUserName()).thenReturn("postgres");
    when(dbModelObject.getPassword()).thenReturn("postgres");

    try
    {
        dbConnector.connectionInit();
    } catch (Exception e)
    {
        assertTrue(e instanceof ClassNotFoundException);
    }

    verify(dbModelObject).getDriver();
}

@Test
public void testConnectionFailure()
{
    when(dbModelObject.getDriver()).thenReturn("org.postgresql.Driver");
    when(dbModelObject.getDatabaseURL()).thenReturn("jdbc:postgresql://127.0.0.1:5432/testdb");
    when(dbModelObject.getUserName()).thenReturn("uname");
    when(dbModelObject.getPassword()).thenReturn("uname");
    try
    {
        dbConnector.connectionInit();
    } catch (Exception e)
    {
        assertTrue(e instanceof SQLException);
    }

    verify(dbModelObject).getDriver();
    verify(dbModelObject).getDatabaseURL();
    verify(dbModelObject).getUserName();
    verify(dbModelObject).getPassword();
}
}

3 个答案:

答案 0 :(得分:2)

您只需使用@Test Annotation

即可

@Test(预期= RuntimeException.class)

另一种解决方案是,当您预期异常时,您应该让测试失败

@Test
public void testConnectionFailure()
{
    ...
    try
    {
        dbConnector.connectionInit();
        fail("an exception should be thrown...")
    } catch (Exception e)
    {
        assertTrue(e instanceof SQLException);
    }
    ...
}  

更新#1:

我认为您的代码和测试用例不是很好,因为在您的代码中,您正在捕获所有“好”异常!但他们告诉你什么是错的。

因此,让您的代码抛出这些异常。

但另一方面是:为什么要为标准 java java.sql 功能(ClassLoading,DriverManager)编写测试用例?

更新#2:

我将以你的例子来解释,因为我不是英国人。 ;)

您的密码:

try
{
        Class.forName(dbObject.getDriver());  
} catch (Exception e)
{
        Logger lgr = Logger.getLogger(PostgreLocationManager.class.getName());
        lgr.log(Level.SEVERE, e.getMessage(), e);
}

您的密码:

try
{
        Do something from java standard. //Class.forName(dbObject.getDriver());  
} if an exception occures, go in this block //catch (Exception e) 
{
        Just print out the exception. 
        If someone knowns about your application he'll take a look in the log. 
        If not, your exception is lost, after leaving this block.
        And I think here is your problem!
        Do not catch any exceptions in a so low level of your application.
}

您的测试用例:

@Test
public void testDriverFailure()
{
    ....
    try
    {
        dbConnector.connectionInit();
    } catch (Exception e)
    {
        assertTrue(e instanceof ClassNotFoundException);
    }
}

您的测试用语:

@Test
public void testDriverFailure()
{
    ....
    try
    {
        try to init your dbConnector. 
    } Catch exceptions (
          They never thrown, because you already catched them in the method connectionInit().
          And here right now, you know, why its a bad idea 
          to catch exceptions and place them into logfiles (except in the very high level of your application)!
      )
    {
        Now Check, that the Java-VM ClassLoader (Not your code!!!) will throw an ClassNotFoundException. 
        Why you not trusting the jvm developers? ;)
    }
}

答案 1 :(得分:0)

您在代码中捕获异常并向日志写入内容。因此,测试无法看到异常,您无法测试它是否被抛出。但是你可以测试你记录了什么。另一种方法是测试你的代码不会抛出异常并返回null。

答案 2 :(得分:0)

当前编写的方法connectionInit ()不会抛出任何异常。在您的两个测试用例中,您应该检查预期的失败(从我可以理解的代码中查看),但如果没有发生故障,则不要调用fail () JUnit方法,因此您会产生这样的印象:测试用例都会通过,而它们都应该失败。正如Mirko所提到的,您应该在调用fail ()后更改代码以致电connectionInit ()