存根方法时获取 InvalidUseOfMatchersException [英] Getting a InvalidUseOfMatchersException when stubbing a method

查看:34
本文介绍了存根方法时获取 InvalidUseOfMatchersException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个TestNG测试方法代码:

I have this TestNG test method code:

@InjectMocks
private FilmeService filmeService = new FilmeServiceImpl();

@Mock
private FilmeDAO filmeDao;

@BeforeMethod(alwaysRun=true)
public void injectDao() {
    MockitoAnnotations.initMocks(this);
}

//... another tests here

@Test
public void getRandomEnqueteFilmes() {
    @SuppressWarnings("unchecked")
    List<Filme> listaFilmes = mock(List.class);

    when(listaFilmes.get(anyInt())).thenReturn(any(Filme.class));
    when(filmeDao.listAll()).thenReturn(listaFilmes);

    List<Filme> filmes = filmeService.getRandomEnqueteFilmes();

    assertNotNull(filmes, "Lista de filmes retornou vazia");
    assertEquals(filmes.size(), 2, "Lista não retornou com 2 filmes");
}

我收到了一个org.mockito.exceptions.misusing.InvalidUseOfMatchersException:参数匹配器的无效使用!0 匹配器预期,1 记录:"在此代码的 listAll() 方法的调用中:

And I'm getting a "org.mockito.exceptions.misusing.InvalidUseOfMatchersException: Invalid use of argument matchers! 0 matchers expected, 1 recorded:" in the call of listAll() method in this code:

@Override
public List<Filme> getRandomEnqueteFilmes() {
    int indice1, indice2 = 0;
    List<Filme> filmesExibir = new ArrayList<Filme>();
    List<Filme> filmes = dao.listAll();

    Random randomGenerator = new Random();
    indice1 = randomGenerator.nextInt(5);
    do {
        indice2 = randomGenerator.nextInt(5);
    } while(indice1 == indice2);

    filmesExibir.add(filmes.get(indice1));
    filmesExibir.add(filmes.get(indice2));

    return filmesExibir;
}

我很确定我在这里遗漏了一些东西,但我不知道它是什么!有人帮忙吗?

I'm prety sure I'm missing something here but I don't know what it is! Someone help?

推荐答案

when(listaFilmes.get(anyInt())).thenReturn(any(Filme.class));

这是你的问题.您不能在返回值中使用 any.any 是一个匹配器——它用于匹配参数值以进行存根和验证——并且在定义调用的返回值时没有意义.您需要显式返回一个 Filme 实例,或者将其保留为 null(这是默认行为,这会破坏存根点).

There's your problem. You can't use any in a return value. any is a Matcher—it's used to match parameter values for stubbing and verification—and doesn't make sense in defining a return value for a call. You'll need to explicitly return a Filme instance, or leave it null (which is the default behavior, which would defeat the point of stubbing).

我应该注意到,使用真正的 List 而不是模拟 List 通常是个好主意.与您开发的自定义代码不同,List 实现定义明确且经过充分测试,并且与模拟 List 不同,如果您重构被测系统以调用不同的方法,则真正的 List 不太可能损坏.这是一个风格和测试理念的问题,但你可能会发现在这里使用一个真正的 List 是有利的.

I should note that it's often a good idea to use a real List instead of a mock List. Unlike custom code you've developed, List implementations are well-defined and well-tested, and unlike mock Lists a real List is very unlikely to break if you refactor your system under test to call different methods. It's a matter of style and testing philosophy, but you may find it advantageous just to use a real List here.

为什么上述规则会导致该异常?嗯,这个解释打破了 Mockito 的一些抽象,但是匹配器的行为不像你想象的那样——它们记录了一个值到 ArgumentMatcher 对象的秘密 ThreadLocal 堆栈上并返回 null 或其他一些虚拟值,并且在对 whenverify 的调用中,Mockito 看到一个非-empty stack 并且知道优先使用这些匹配器而不是实际参数值.就 Mockito 和 Java 评估顺序而言,您的代码如下所示:

Why would the above rule cause that exception? Well, this explanation breaks some of Mockito's abstractions, but matchers don't behave like you think they might—they record a value onto a secret ThreadLocal stack of ArgumentMatcher objects and return null or some other dummy value, and in the call to when or verify Mockito sees a non-empty stack and knows to use those Matchers in preference to actual argument values. As far as Mockito and the Java evaluation order are concerned, your code looks like the following:

when(listaFilmes.get(anyInt())).thenReturn(null);
when(filmeDao.listAll(any())).thenReturn(listaFilmes); // nonsense

自然 Mockito 看到一个 any 匹配器,而 listAll 不接受参数,所以有 0 个预期匹配器,1 个记录.

Naturally Mockito sees an any matcher, and listAll doesn't take an argument, so there are 0 matchers expected, 1 recorded.

这篇关于存根方法时获取 InvalidUseOfMatchersException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆