有关于在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();
}
}
答案 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 ()
。