Mockito模拟的方法返回了NULL

4
我正在使用Mockito并尝试模拟下面的测试类。 这里的主要类方法createNewId()通过调用dao类“memberDao.findNext()”获取对象。 我试图模拟'memberDao.findNext()'并按照下面的代码返回对象,但它返回为NULL。
此外,如何编写void方法的测试,即“memberDao.delete(newId.getId());” 需要在这行代码“when(memberDao.findNext()).thenReturn(id);”之后实现它。
请让我知道我做错了什么。
@RunWith(MockitoJUnitRunner.class)
public class MemberTest
{
    @InjectMocks
    private Member member;
    @Mock
    private MemberDao memberDao;

    @Test
    public void createId() throws Exception
    {
        MembersIdDto id = new MembersIdDto();
        id.setId("967405286");
        when(memberDao.findNext()).thenReturn(id);
        verify(member).createNewId().contains("967405286");
    }


    public class Member {
    @Resource
    MemberDao memberDao;

    public String createNewId()
    {
        MembersIdDto newId = memberDao.findNext();   
        Assert.notNull(newId, "newId is empty");
        String id = newId.getId();
        memberDao.delete(newId.getId());
        return id;
    }
    }

我试图模拟的是memberDao.findNext()这行代码。

错误信息为: java.lang.IllegalArgumentException: newId为空

at org.springframework.util.Assert.notNull(Assert.java:134)
at Member.createNewId() (Member.java:20)

// 第20行代码是"Assert.notNull(newId, "newId is empty");"


manager的类型是什么?这不是被测试的类吗?我在你的@Test方法中看不到任何对生产代码的调用。 - mle
1
请注意,您可以使用@Mock来创建模拟对象,或者手动创建Mockito.mock(MemberDao.class)。两种方式都使用是多余的。 - mle
哦!我的错。我已经更新了代码。它是Member类,而不是MainClass。 - Rahul
很酷,我在我的回答中发布了一个相应的工作示例。 - mle
2个回答

3
您的要求的一个可行示例可能是:

一个工作示例:

@RunWith(MockitoJUnitRunner.class)
public class MemberTest {
    @InjectMocks
    private Member member;
    @Mock
    private MemberDao memberDao;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void createId() throws Exception {
        MembersIdDto dto = new MembersIdDto();
        dto.setId("967405286");
        when(memberDao.findNext()).thenReturn(dto);

        assertThat(member.createNewId()).isEqualTo("967405286");
    }
}

...使用作为测试类的类...

public class Member {
    @Resource
    MemberDao memberDao;

    public String createNewId() {
        return memberDao.findNext().getId();
    }
}

…和…

public class MemberDao {
    public MembersIdDto findNext() {
        return null; // or whatever
    }
}

…和…

import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
public class MembersIdDto {
    private String id;
}

顺便提一下,我使用 AssertJ断言框架,并且通过 member.createNewId(),您现在可以在生产代码中进行真正的调用。


1
您正在创建两个MemberDao实例。首先MockitoJUnitRunner创建一个实例,将其分配给字段memberDao并将该实例注入Member对象中。然后,在方法setUp中,您创建了一个新的DAO实例并将其分配给字段memberDao。因此,字段memberDao不再与Member的DAO相同。虽然您在字段上定义了行为,但Member对象仍在使用没有定义行为的第一个DAO。因此,Member#createNewId中的memberDao.findNext()返回null

幸运的是,解决方案非常简单:删除测试中的setUp方法。


这个答案对我有所帮助,但是是迂回的方式。在我的情况下,我正在使用Spring的@MockBean注释,然后还错误地使用mock(MyClassName.class)进行实例化。因此,在删除手动实例化之后,它就可以工作了。 - Nathan Karasch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接