对没有实现的接口的JUnit测试

时间:2013-12-15 21:11:50

标签: testing interface junit mockito

我尝试使用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);

    [...]
}

在我意识到它完全没有意义之后我试图模仿界面,所以我有点迷失。也许有人可以给我一个我可以合作的好方法。我也听说过junit参数化测试,但我不确定这是不是我要找的。

非常感谢!

2 个答案:

答案 0 :(得分:5)

我使用以下模式为我的接口API编写抽象测试,而不提供任何实现。您可以在AbstractShortMessageServiceTest中编写所需的任何测试,而无需在该时间点实现它们。

public abstract class AbstractShortMessageServiceTest
{
    /**
     * @return A new empty instance of an implementation of FooManager.
     */
    protected abstract ShortMessageService getNewShortMessageService();

    private ShortMessageService testService;

    @Before
    public void setUp() throws Exception
    {
        testService = getNewShortMessageService();
    }

    @Test
    public void testFooBar() throws Exception 
    {
        assertEquals("question", testService.createMessage(
                                             "DeepThought", "42", "everything"));
    }
}

如果有实现,只需定义一个覆盖AbstractShortMessageServiceTest并实现getNewShortMessageService方法的新测试类即可使用测试。

public class MyShortMessageServiceTest extends AbstractShortMessageServiceTest
{
    protected ShortMessageService getNewShortMessageService()
    {
        return new MyShortMessageService();
    }
}

此外,如果您需要参数化测试,您可以在AbstractShortMessageServiceTest中执行此操作,而无需在每个具体测试中执行此操作。

答案 1 :(得分:0)

通常测试是为实现接口的类准备的,而mocks用于合作类,但是你可以通过模拟测试你的测试是否尚未准备好。这是不寻常的,您应该使用thenAnsfer实现可能情况的逻辑:

更好的方法是简单地为实现类准备测试并开始改进它直到所有测试通过: 实现类可以在字段中并在测试之前初始化

private ShortMessageService testedClasOrMock;

//version with implementing class
@Before
public void setUp(){
      testedClasOrMock = new ShortMessageServiceImpl0();
}

@Before
public void setUp(){
    testedClasOrMock = mock(ShortMessageService.class);
    when(testedClasOrMock).thenAnswer(new Answer<Long>(){

        @Override
        public Long answer(InvocationOnMock invocation) throws Throwable {
            String message =(String) invocation.getArguments()[1];
            if (message.length() > 256){
                throw new IllegalArgumentException("msg is too long");
            }
                            //other exception throwing cases 
                            …...
            return new Long(44);
        }});
}

所以你将有几个测试与预期的例外,如

 @Test (expected= IllegalArgumentException.class)
 public void testTooLongMsg(){
    testedClasOrMock.createMessage(USER, TOO_LONG_MSG, TOPIC);
 }

和一个不应该抛出异常,例如检查msg id是不同的

 @Test
 public void testTooLongMsg(){
    long id0 =  testedClasOrMock.createMessage(USER, TOO_LONG_MSG, TOPIC);
    long id1 =  testedClasOrMock.createMessage(USER, TOO_LONG_MSG, TOPIC);
    assertTrue(id0 != id1);
 }

如果您坚持通过模拟测试您的测试,请告诉我,我将为一个测试用例添加示例。