-1

有一个关于在 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();
}
}
4

3 回答 3

2

您可以简单地使用 @Test 注解

@Test(expected=RuntimeException.class)

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

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

更新#1:

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

所以让你的代码抛出这些异常。

但另一方面是:为什么要为标准javajava.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? ;)
    }
}
于 2013-10-21T10:26:14.293 回答
0

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

于 2013-10-21T11:54:31.193 回答
0

当前编写的方法connectionInit ()不会引发任何异常。在您的两个测试用例中,您应该检查预期的失败(根据我对您的代码的理解),但是fail ()如果没有发生失败,您不会调用 JUnit 方法,因此您的印象是您的测试用例都通过了他们都应该失败。正如 Mirko 提到的,您应该fail ()在调用connectionInit ().

于 2013-10-21T12:22:47.740 回答