Mockito中when(...).thenReturn(...)失效,resendClient.emails()返回null求助
我在编写单元测试时遇到Mockito模拟失效问题,测试代码如下:
@UnitTest @RunWith(MockitoJUnitRunner.class) public class ResendMailingStrategyUnitTest { @Test public void sendTest() throws ResendException { Resend resendClient = Mockito.mock(Resend.class); Emails mockedEmails = Mockito.mock(Emails.class); ResendMailingStrategy resendMailingStrategy = new ResendMailingStrategy(); ReflectionTestUtils.setField(resendMailingStrategy, "resendClient", resendClient); Mockito.when(resendClient.emails()).thenReturn(mockedEmails); Mockito.when(mockedEmails.send(Mockito.any(CreateEmailOptions.class))).thenReturn(null); resendMailingStrategy.send(StubProvider.getEmailMessageModelStub()); Mockito.verify(resendClient).emails().send(Mockito.any(CreateEmailOptions.class)); } }
设置Mockito.when(resendClient.emails()).thenReturn(mockedEmails)后,resendClient.emails()仍返回null,导致报错:
Cannot invoke "com.resend.services.emails.Emails.send(com.resend.services.emails.model.CreateEmailOptions)" because the return value of "com.resend.Resend.emails()" is null
修复方案
检查Resend类的emails()方法是否为final
Mockito默认无法模拟final方法,如果emails()是final的,需启用Mockito的final方法模拟支持:
在src/test/resources/mockito-extensions目录下创建文件org.mockito.plugins.MockMaker,内容写入mock-maker-inline即可。调整verify语句的写法
原verify语句会尝试链式调用方法,模拟失效时会触发NPE。应拆分验证逻辑:Mockito.verify(resendClient).emails(); Mockito.verify(mockedEmails).send(Mockito.any(CreateEmailOptions.class));验证ReflectionTestUtils字段设置是否成功
可添加断言确认字段注入正确:Assertions.assertSame(resendClient, ReflectionTestUtils.getField(resendMailingStrategy, "resendClient"));若字段名错误或为private final,会导致注入失败,需核对字段名称与访问权限。
改用@Mock注解管理模拟对象
替换手动创建模拟对象的方式,用注解更简洁可靠:@UnitTest @RunWith(MockitoJUnitRunner.class) public class ResendMailingStrategyUnitTest { @Mock private Resend resendClient; @Mock private Emails mockedEmails; private ResendMailingStrategy resendMailingStrategy; @Before public void setUp() { resendMailingStrategy = new ResendMailingStrategy(); ReflectionTestUtils.setField(resendMailingStrategy, "resendClient", resendClient); Mockito.when(resendClient.emails()).thenReturn(mockedEmails); Mockito.when(mockedEmails.send(Mockito.any(CreateEmailOptions.class))).thenReturn(null); } @Test public void sendTest() throws ResendException { resendMailingStrategy.send(StubProvider.getEmailMessageModelStub()); Mockito.verify(resendClient).emails(); Mockito.verify(mockedEmails).send(Mockito.any(CreateEmailOptions.class)); } }
内容的提问来源于stack exchange,提问作者Nicolas Villacorta

