使用mockito进行单元测试时抛出WrongTypeOfReturnValue异常

时间:2014-03-24 17:29:14

标签: java unit-testing mocking tdd mockito

我的测试

List<Person> myList;

@Test
public void testIsValidPerson() {
    myList = new ArrayList<Person>();

    myList.add(new Person("Tom"));
    when(personDao.get(person)).thenReturn(myList);
    when((personDao.get(person)).isEmpty()).thenReturn(false);//------Exception thrown 

    boolean result = service.isValid("Tom");
    assertFalse(result);
}

要测试的方法:

public boolean isValid(String person){
    personDao = new PersonDao();
    Person personObj = new Person(person);
    return (personDao.get(person).isEmpty())?false : true;      
}

抛出异常:

org.mockito.exceptions.misusing.WrongTypeOfReturnValue: 
Boolean cannot be returned by get()
get() should return List
***
If you're unsure why you're getting above error read on.
Due to the nature of the syntax above problem might occur because:
1. This exception *might* occur in wrongly written multi-threaded tests.
   Please refer to Mockito FAQ on limitations of concurrency testing.
2. A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies - 
   - with doReturn|Throw() family of methods. More in javadocs for Mockito.spy() method.

使用间谍的第二种方法:

public void testIsValidPerson() {
    myList = new ArrayList<Person>();

    myList.add(new Person("Tom"));
    when(personDao.get(person)).thenReturn(myList);

    List<Person> mylist = personDao.get(person);
    List spy = spy(mylist);

    doReturn(false).when(spy.isEmpty());//------exception thrown

    boolean result = service.isValid("Tom");
    assertFalse(result);
}

这给了我以下例外:

org.mockito.exceptions.misusing.UnfinishedStubbingException: 
Unfinished stubbing detected here:
-> at com.PersonTest.testIsValid(PersonTest.java:76)

E.g. thenReturn() may be missing.
Examples of correct stubbing:
    when(mock.isOk()).thenReturn(true);
    when(mock.isOk()).thenThrow(exception);
    doThrow(exception).when(mock).someVoidMethod();
Hints:
 1. missing thenReturn()
 2. you are trying to stub a final method, you naughty developer!

第三个appraoch:

@Test
public void testIsValidPerson() {
    myList = new ArrayList<Person>();

    myList.add(new Person("Tom"));
    when(personDao.get(person)).thenReturn(myList);

    boolean result = service.isValid("Tom");//--------Throws null pointer exception
    assertFalse(result);
}

public boolean isValid(String person){
    personDao = new PersonDao();
    Person personObj = new Person(person);
    return (personDao.get(person).isEmpty())?false : true;  //----throws NPE    
}

第四种方法:抛出空指针异常

@Test
public void testIsValidPerson() {
    List<Person> mockedList = mock(List.class);
    when(personDao.get(person)).thenReturn(mockedList);
    when(personDao.get(person)).isEmpty().thenReturn(false);
    boolean result = service.isValid("Tom");//--------Throws null pointer exception
    assertFalse(result);
}

public boolean isValid(String person){
    personDao = new PersonDao();
    Person personObj = new Person(person);
    return (personDao.get(person).isEmpty())?false : true;  //----throws NPE    
}

第五种方法:也给NPE。

personDao的get方法访问数据库,并在获取与DB的连接时抛出NPE。但是当我得到一个空列表时,它并没有第一次给NPE。我在service.isValid()

的第二个电话中获得了NPE
@Test
public void testIsValidPerson() {
    when(personDao.get(person)).thenReturn(new ArrayList<Person>());
    List tempList=personDao.get(person);//----I get empty tempList---No NPE
    boolean result = service.isValid("Tom");//--------Throws null pointer exception
    assertFalse(result);
}

方法6:

@Test
public void testIsValid() {
    personList = new ArrayList<Person>();
    Person person = new Person("Tom");
    personList.add(person);
    when(personDao.get(person)).thenReturn(personList);//-------Uses same person object

    boolean result = service.isValid(person);//------------Uses same person object
    assertTrue(result);
}

我改变了我的方法签名(以便测试和测试中的方法使用相同的值)。

public boolean isValid(String name)

public boolean isValid(Person person)

2 个答案:

答案 0 :(得分:2)

基本上你没有足够的嘲笑。 您正在尝试模拟模拟对象返回的isEmpty的{​​{1}}方法。你有一个模拟对象,但你没有让mock对象返回一个模拟列表,所以你可以模拟一个模拟列表的方法......

我不明白的一件事是你为什么要创建一个包含元素的列表,但对List

返回true

如果您需要测试代码获取空列表时的行为方式,请创建一个空列表。这样isEmpty将自动返回false。

isEmpty

答案 1 :(得分:1)

when((personDao.get(person)).isEmpty()).thenReturn(false);毫无意义,因为personDao.get(person)不是模拟。它只是myList,因为你在上面的那条线上以这种方式存根。所以这与执行when(myList.isEmpty()).thenReturn(false);完全相同 - 但你不能存根,因为这里没有模拟。