我有一个指定良好的接口,而且我编写了JUnit测试:
public interface ShortMessageService {
/**
* Creates a message. A message is related to a topic
* Creates a date for the message
* @throws IllegalArgumentException, if the message is longer then 255 characters.
* @throws IllegalArgumentException, if the message ist shorter then 10 characters.
* @throws IllegalArgumentException, if the user doesn't exist
* @throws IllegalArgumentException, if the topic doesn't exist
* @throws NullPointerException, if one argument is null.
* @param userName
* @param message
* @return ID of the new created message
*/
Long createMessage(String userName, String message, String topic);
[...]
}
正如您所看到的,实现可以抛出各种异常,我必须编写测试。我目前的方法是为接口中指定的一个可能的异常编写一个测试方法,如下所示:
public abstract class AbstractShortMessageServiceTest
{
String message;
String username;
String topic;
/**
* @return A new empty instance of an implementation of ShortMessageService.
*/
protected abstract ShortMessageService getNewShortMessageService();
private ShortMessageService messageService;
@Rule
public ExpectedException thrown = ExpectedException.none();
@Before
public void setUp() throws Exception
{
messageService = getNewShortMessageService();
message = "Test Message";
username = "TestUser";
topic = "TestTopic";
}
@Test
public void testCreateMessage()
{
assertEquals(new Long(1L), messageService.createMessage(username, message, topic));
}
@Test (expected = IllegalArgumentException.class)
public void testCreateMessageUserMissing() throws Exception
{
messageService.createMessage("", message, topic);
}
@Test (expected = IllegalArgumentException.class)
public void testCreateMessageTopicMissing() throws Exception
{
messageService.createMessage(username, message, "");
}
@Test (expected = IllegalArgumentException.class)
public void testCreateMessageTooLong() throws Exception
{
String message = "";
for (int i=0; i<255; i++) {
message += "a";
}
messageService.createMessage(username, message, topic);
}
@Test (expected = IllegalArgumentException.class)
public void testCreateMessageTooShort() throws Exception
{
messageService.createMessage(username, "", topic);
}
@Test (expected = NullPointerException.class)
public void testCreateMessageNull() throws Exception
{
messageService.createMessage(username, null, topic);
}
[...]
}
所以现在我必须为接口中定义的那个方法定义很多测试方法,这感觉很尴尬。我可以在一种测试方法中结合所有这些异常测试,还是最佳实践?
答案 0 :(得分:5)
不幸的是,@ Test注释不允许捕获多个异常类型(api reference http://junit.sourceforge.net/javadoc/org/junit/Test.html)。
作为第一种选择,我主张转向TestNG。如果您的团队不允许这样做,那么您在JUnit中可以做的事情很少。
绝对使用参数化测试用例,这样您就不必为每个测试用例编写一个测试函数(http://junit.sourceforge.net/javadoc/org/junit/runners/Parameterized.html)。从这里开始,有几个选择。
按例外类型对测试数据进行分组。
@Test (expected = IllegalArgumentException.class)
public void testIllegalArgumentException(String username, String message, String topic) {}
@Test (expected = NullPointerException.class)
public void testNullPointerException(String username, String message, String topic) {}
在方法签名中组合异常类型。 (这是我推荐的)下面的粗略轮廓......
public void testException(String username, String message, String topic, Class<? extends Exception>[] expectedExceptionClasses) {
try {
// exception throwing code
} catch (Exception e) {
boolean found = false;
for (Class<?> expectedException : expectedExceptions) {
if (e instanceof expectedException) {
found = true;
}
}
if (found) {
return;
}
}
Assert.fail();
}
将所有测试放在保护伞类别下面(我觉得你不想这样做。)。
@Test (expected = Exception.class)
public void testException(String username, String message, String topic) {}
答案 1 :(得分:0)
将它们全部合并到一个方法中可能不是最好的主意,因为你不会真正知道哪个测试用例抛出了哪个异常。
例如,如果你有一行
messageService.createMessage(username, null, topic);
应该抛出一个NullPointerException
,而是抛出一个IllegalArgumentException
,你不希望这被视为成功。
如果您想在一个测试用例中测试该方法的所有异常,那么一个好的替代方法是将每个异常测试包装在try..catch块中。
例如,您可以
@Test
public void testCreateMessageExceptions() {
// test #1: a null message
try {
messageService.createMessage(username, null, topic);
// if it got this far, that's a problem!
fail();
} catch(NullPointerException e) {
// great, that's what it's meant to do! continue testing
} catch(Exception e) {
// if it threw the wrong type of exception, that's a problem!
fail();
}
// test #2: an empty user
try {
messageService.createMessage("", message, topic);
fail();
} catch(IllegalArgumentException e) {
} catch(Exception e) {
fail();
}
// ...
}