微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在以下测试用例上获取NotAMockException

如何解决在以下测试用例上获取NotAMockException

我尝试运行以下测试,并且遇到NotAMock异常,不确定如何解决。我一直在尝试读一个概念,即不能嘲笑被测类的方法,但是我无法在这主题上弄清楚。如果有人能以我的榜样向我解释“为什么”,我希望能更好地理解它。

我尝试了多种方法来更改@RunWith运行器以进行单元或集成测试设置,或者使用@Spy代替@Mock或没有@Autowired等,但是都面临dao Null指针或非模拟异常会有所不同。

我应该使用另一个类并将Listener注入该类中并模拟侦听器,以实现能够模拟方法并动态捕获参数的功能。这将因为不再受测试的类而起作用,因此可以模拟这些方法吗?如果是这样,这是如何实现的。如果没有,正确的方法是什么。我的感觉是将侦听器移到另一个类只会扩展当前无法模拟但无法解决的一系列问题。但是,我不确定什么是正确的结果。

@Component
public class FileEventListener implements ApplicationListener<FileEvent> {

    @Autowired private FetchFileDetailsDAO fileDao;//Dao is annotated with @Transactional

    @Override
    public void onApplicationEvent(FileEvent event) {
        fileDao.getDetailsForFile(event.fileName())
    }     
}
-----------------------------------------------------------------------------------------

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.springframework.boot.test.context.SpringBoottest;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.junit4.springrunner;
import org.springframework.transaction.annotation.Transactional;

@SpringBoottest(classes = TestApp.class)
@RunWith(springrunner.class)
public class TestClass {  
  
@Captor private ArgumentCaptor<Object> captor;
@Mock @Autowired private FetchFileDetailsDAO dao;
@InjectMocks @Autowired private FileEventListener listener;

@Before
public void setup() throws IOException {
    MockitoAnnotations.initMocks(this);
}

@Test
@Transactional
@Rollback(true)
public void test() throws Exception {
    FileEvent ev = new FileEvent();
    ...
    listener.onApplicationEvent(ev);
    verify(dao,times(1)).getDetailsForFile((String)captor.capture())
}

解决方法

您正在把事情混在一起。 @Mock@MockBean之间有重要区别。

如果要编写没有任何Spring Context支持(说@SpringBootTest@DataJpaTest等)的单元测试,请使用第一个注释。对于此类测试,可以使用@Mock@InjectMocks

在编写集成测试时(以@SpringBootTest开始整个上下文),您将在测试中使用托管Spring Bean。因此,您不再编写 unit 测试。

如果要在Spring Test Context中用其模拟版本替换Spring bean,则必须使用@MockBean

@SpringBootTest(classes = TestApp.class)
@RunWith(SpringRunner.class)
@RunWith(MockitoJUnitRunner.class) // will do the Captor initialization for you
public class TestClass {  

  @Captor 
  private ArgumentCaptor<Object> captor;

  @MockBean 
  private FetchFileDetailsDAO dao;

  @Autowired 
  private FileEventListener listener;


  @Test
  @Transactional
  @Rollback(true)
  public void test() throws Exception {
    FileEvent ev = new FileEvent();
    // ...
    listener.onApplicationEvent(ev);
    verify(dao,times(1)).getDetailsForFile((String)captor.capture())
  }

不过,恕我直言 overkill 是本次测试的全部内容。最好使用 just JUnit和Mockito编写一个好的旧单元测试。

除此之外,我还要重新考虑一下您当前的测试为您的项目带来的好处,因为它实际上是在复制业务逻辑。也许这里没有更多的代码。

您可以找到difference between @Mock and @MockBean in this article的详细摘要。

,

我认为问题在于以下几行

@Mock @Autowired private FetchFileDetailsDAOImpl dao;

改为尝试@Mock private FetchFileDetailsDAOImpl dao;

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。