栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

Mockito何时/然后不返回期望值

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Mockito何时/然后不返回期望值

单元测试的问题是,您正在尝试模拟您要测试的实际类的方法,但实际上无法调用模拟方法,因为这将返回null,除非您在该方法上声明了模拟的返回值调用的方法。通常,您只模拟外部依赖关系。

实际上,有两种创建测试对象的方法:

mock
spy
。入门之一将根据您提供的类创建一个新对象,该类的内部状态为null,并且
null
在每个调用的方法上都返回。因此,您需要为方法调用定义某些返回值。
spy
另一方面,如果为某些方法定义了“模拟定义”,则创建一个真实的对象并拦截方法调用。

Mockito和PowerMock提供了两种定义模拟方法的方法:

// method 1when(mockedObject.methodToMock(any(Param1.class), any(Param2.class),...)    .thenReturn(answer);when(mockedObject, method(Dependency.class, "methodToMock", Parameter1.class, Parameter2.class, ...)    .thenReturn(answer);

要么

// method 2doReturn(answer).when(mockedObject).methodToMock(param1, param2);

不同之处在于,

method1
会执行方法的实现,而后一个则不会。如果您要处理
spy
对象,这很重要,因为您有时不想执行所调用方法中的真实代码,而只是替换代码或返回预定义的值!

尽管Mockito和PowerMock提供了一个

doCallRealMethod()
您可以定义的,而不是
doReturn(...)
or
doThrow(...)
,但是它将在您的真实对象中调用并执行代码,并且忽略任何模拟的方法返回语句。但是,在您要模拟被测类的方法的情况下,此功能不是那么有用。

可以通过以下方法“覆盖”方法实现:

doAnswer(Answer<T>() {     @Override     public T answer(InvocationOnMock invocation) throws Throwable {        ...    })

您可以在其中简单地声明所调用方法的逻辑。因此,您可以利用此方法返回受保护方法的模拟结果:

import static org.hamcrest.core.IsSame.sameInstance;import static org.junit.Assert.assertThat;import static org.mockito.Mockito.mock;import static org.mockito.Mockito.spy;import static org.mockito.Mockito.doReturn;import static org.mockito.Mockito.doAnswer;import static org.mockito.Matchers.any;import static org.mockito.Matchers.anyString;import java.io.InputStream;import org.junit.Test;import org.mockito.invocation.InvocationOnMock;import org.mockito.stubbing.Answer;public class FooKeyRetrieverTest {    @Test    public void testGetFooKey() throws Exception {        // Arrange        final FooKeyRetriever sut = spy(new FooKeyRetriever());        FooKey mockedKey = mock(FooKey.class);        doReturn(mockedKey) .when(sut).getKeyFromStream(any(InputStream.class), anyString());        doAnswer(new Answer<FooKey>() { public FooKey answer(InvocationOnMock invocation) throws Throwable {     return sut.getKeyFromStream(null, ""); }        }).when(sut).getKey(anyString());        // Act        FooKey ret = sut.getKey("test");        // Assert        assertThat(ret, sameInstance(mockedKey));    }}

上述工程的代码,但是请注意,这有相同的语义简单地宣布了一个返回值

getKey(...)
作为

doReturn(mockedKey).when(sut).getKey(anyString());

尝试仅

getKeyFromStream(...)
使用以下内容进行修改:

doReturn(mockedKey)    .when(sut).getKeyFromStream(any(InputStream.class), anyString());

如果不修改

getKey(...)
系统测试中的内容(SUT),将不会实现任何效果,因为
getKey(...)
将执行真正的代码。但是,如果模拟sut对象,则无法调用本
//Act
节中的方法,因为这将返回null。如果你试试

doCallRealMethod().when(sut).getKey(anyString());

在模拟对象上,将调用真实方法,并且如前所述,这还将调用的实际实现,

getKeyFromStream(...)
getKeyStream(...)
无论您指定为模拟方法是什么。

正如您可能自己看到的那样,测试中的实际类的模拟方法不是那么有用,并且给您带来的负担超过了它提供的任何好处。因此,如果您想要或需要完全测试私有/受保护的方法,或者仅坚持测试公共API(我建议这样做),则取决于您或您企业的政策。尽管重构的主要目的应该是改善代码的整体设计,但是您也可以重构代码以提高可测试性。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/497301.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号