Mockito returns 不同参数值相同的结果

Mockito returns the same result for different parameter values

我在使用 Mockito 时遇到了这种奇怪的行为,但我不确定这是否是任何方式的预期行为:-(。以下代码是我想出的虚构 Java 代码来强调这一点。

import org.junit.Test;
import org.mockito.Mockito;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.Mockito.when;

public class StringServiceTest {

    enum Style {
        NONE, ITALIC, BOLD
    }

    private class StringService {

        public List<String> getString(Set<String> words, long fontSize, Style fontStyle) {
            return new ArrayList<>();
        }
    }

    @Test
    public void testGetString() {

        StringService stringService = Mockito.mock(StringService.class);

        Set<String> words = new HashSet<>();
        List<String> sentence = new ArrayList<>();

        when(stringService.getString(words, 12L, Style.BOLD)).thenReturn(sentence);

        List<String> result = stringService.getString(words, 234L, Style.ITALIC);
        List<String> result1 = stringService.getString(words, 565L, Style.ITALIC);
        List<String> result2 = stringService.getString(words, 4545L, Style.NONE);

        assertThat("Sentences are different", result.hashCode() == result1.hashCode());
        assertThat("Sentences are different", result.hashCode() == result2.hashCode());
    }
}

由于 Mockito 无法读取源代码,因此它依赖于代码的静态状态来记录每次调用时应返回的内容。但是这种行为完全让我感到困惑,因为它 returns 同一个对象用于不同的参数,而当它应该为一组它没有编程的参数发送 null 或空对象时。 我在 Junit 4.11 中使用 Java 1.7.0_79 和 Mockito 1.10.19。 我是不是漏掉了什么重要的东西,或者有人可以解释一下这种行为吗?

因为你在嘲笑 class,所以它 return 是一个通用的 return 值。这不是 returning 你想的那样。在本例中,它是 LinkedList。列表hashCode取决于内容:

/**
 * Returns the hash code value for this list.
 *
 * <p>This implementation uses exactly the code that is used to define the
 * list hash function in the documentation for the {@link List#hashCode}
 * method.
 *
 * @return the hash code value for this list
 */
public int hashCode() {
    int hashCode = 1;
    for (E e : this)
        hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
    return hashCode;
}

如果把hashCode打印出来,会发现是1

您只存根了以下调用

when(stringService.getString(words, 12L, Style.BOLD)).thenReturn(sentence);

与您的任何调用都不匹配

List<String> result = stringService.getString(words, 234L, Style.ITALIC);
List<String> result1 = stringService.getString(words, 565L, Style.ITALIC);
List<String> result2 = stringService.getString(words, 4545L, Style.NONE);

对于未存根的方法,Mockito 使用 RETURN_DEFAULTS

The default Answer of every mock if the mock was not stubbed. Typically it just returns some empty value.

Answer can be used to define the return values of unstubbed invocations.

This implementation first tries the global configuration. If there is no global configuration then it uses ReturnsEmptyValues (returns zeros, empty collections, nulls, etc.)

换句话说,你对 getString 的每一次调用实际上都返回了一些空的 List (Mockito 当前的实现 returns 一个新的 LinkedList 实例)。

由于所有这些 List 个实例都是空的,所以它们都具有相同的 hashCode