Mockito什么时候/然后不返回期望值

乍得

我正在尝试使用“ any”匹配器对这个getKeyFromStream方法进行存根。我尝试了更明确和不太明确的(anyObject()),但似乎无论我如何尝试,此存根都不会在我的单元测试中返回fooKey。

我想知道是否是因为它受到保护,或者我缺少其他东西或做错了什么。在整个测试中,我还有其他的when / then语句在起作用,但是由于某种原因,事实并非如此。

注意:getKeyFromStream通常使用byteArrayInputStream,但是我试图将其与InputStream匹配,但都尝试了无济于事。

public class FooKeyRetriever() //Mocked this guy
{
    public FooKey getKey(String keyName) throws KeyException {

        return getKeyFromStream(getKeyStream(keyName, false), keyName);
    }

    //Stubbed this method to return a key object which has been mocked
    protected FooKey getKeyFromStream(InputStream keyStream, String keyName){
        //Some code
        return fooKey;
    }
}

单元测试

@Mock
private FooKeyRetriever mockKeyRetriever;

@Mock
private FooKey fooKey;

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

@Test
public void testGetFooKey() throws Exception {



    when(foo.getKeyFromStream(any(InputStream.class),any(String.class))).thenReturn(fooKey);

    FooKey fooKey = mockKeyRetriever.getKey("irrelevant_key");

    assertNotNull(fooKey);
}
罗曼·沃特纳

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

实际上,有两种创建测试对象的方法:mockspy入门者将根据您提供的类创建一个新对象,该类的内部状态为null,并且null在每个调用的方法上都返回这就是为什么您需要为方法调用定义某些返回值的原因。spy另一方面,如果为某些方法定义了“模拟定义”,则创建一个真实的对象并拦截方法调用。

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

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

或者

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

不同之处在于,method 1会执行方法的实现,而后一个则不会。如果您要处理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(我建议这样做),则取决于您或您企业的政策。尽管重构的主要目的应该是改善代码的整体设计,但是您也可以重构代码以提高可测试性

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

Mockito什么时候-然后返回错误

来自分类Dev

任务ContinueWith不返回期望值

来自分类Dev

标量UDF不返回期望值

来自分类Dev

为什么映射可枚举的返回值不返回期望值

来自分类Dev

preg_match_all不返回期望值

来自分类Dev

嵌套匹配的索引不返回期望值

来自分类Dev

XNA Rectangle.Center不返回期望值

来自分类Dev

preg_match_all不返回期望值

来自分类Dev

为什么++ i ||不 ++ j && ++ k给出期望值

来自分类Dev

什么时候可以按值返回?

来自分类Dev

当最大值返回NULL时,函数不返回期望值

来自分类Dev

Spock存根未返回期望值

来自分类Dev

COUNTIF公式未返回期望值

来自分类Dev

Ruby命令未返回期望值

来自分类Dev

使用从createFromFormat创建的值添加到DateTime时不返回期望值

来自分类Dev

List.contains为长值不返回期望值(常规)

来自分类Dev

什么时候构造函数参数和返回值?

来自分类Dev

什么时候应该通过值传递或返回结构?

来自分类Dev

什么时候否定 JSDoc 中的返回值?

来自分类Dev

正则表达式组不返回期望值

来自分类Dev

java.awt.image.BufferedImage.getRBG不返回期望值

来自分类Dev

recv()什么时候返回?

来自分类Dev

什么时候返回null?

来自分类Dev

glBufferSubData 什么时候返回?

来自分类Dev

当我在嵌套的for循环中分配期望值后,为什么OpenCV Mat对象不包含期望值?

来自分类Dev

为什么此正则表达式返回期望值的较短版本?

来自分类Dev

SurveyMonkey API返回的各种“ ENUM”类型的期望值是什么?

来自分类Dev

Tumblr。oauth_signature与期望值不匹配。401

来自分类Dev

闹钟什么时候不响