【问题标题】:Springs @Autowiring functionality Along with MockingSprings @Autowiring 功能以及 Mocking
【发布时间】:2015-12-08 11:12:02
【问题描述】:

问题: 我有一个A类

class A {

      @Autowired
      EdocumentDAO eDocumentDAO;

      public void createDocument(DocumentType docType)
      {
            String DocID= saveIndocRepo();//To be Mocked
            docType.setID(DocID);

            isSaved = eDocumentDAO.save()//Autowired

      }
      private String saveIndocRepo()
      {
          //Code to save in Repo in another platform and return the DOC_ID
      }


}

我的 A_Test 课程

@ContextConfiguration({ "classpath:test-beans.xml" })
@RunWith(SpringJUnit4ClassRunner.class)
@ActiveProfiles("test")
class A_test {

        A a = Mockito.spy(new A());

        Mockito.doReturn("DOC_ID").when(a).saveIndocRepo();
        a.createDocument(docType);      
}

要求: 我有方法saveIndocRepo(),它与外部服务交互并将文档保存在他们的仓库中。所以这需要被嘲笑。

createDocument() 中调用并返回一个模拟值。收到DocID 后,其他文档详细信息将保存到数据库中(为此我配置了一个Derby In-memory DB)。 EdocumentDAO 在由弹簧实例化的自动装配上工作。

问题: 当我尝试模拟方法(saveInDocRepo)时,它成功模拟但自动装配失败。这会导致 JUnit 失败。 当我删除模拟时,自动装配会完美执行。

有什么我想念的吗?还是我的方法不正确。 专家 - 请提供适当的解决方案。

【问题讨论】:

    标签: spring spring-mvc mockito junit4


    【解决方案1】:

    谢谢大家的帮助。

    解决方案:

    @ContextConfiguration({ "classpath:test-beans.xml" })
    @RunWith(SpringJUnit4ClassRunner.class)
    @ActiveProfiles("test")
    
    @Spy
    @InjectMocks
    A a = new A();
    
    @Autowired
    @Spy
    EdocumentDAO eDocumentDAO;
    class A_test {
    
            Mockito.doReturn("DOC_ID").when(a).saveIndocRepo();
            a.createDocument(docType);      
    }
    

    现在,当调用 createDocument() 方法时,saveInDocRepo() 被模拟返回“DOC_ID”,并且 eDocumentDAO.save() 可以完美运行。 它用于部分模拟的@Spy 挽救了这一天。

    【讨论】:

      【解决方案2】:

      你必须模拟一个接口而不是类本身。 使用要模拟的类的公共方法创建一个接口。

      在上面的示例中,您正在监视 A,但 A 依赖于 EdocumentDAO。你也必须模拟这个类。

      @Mock
      EdocumentDAO edocumentDAOMock;
      

      或者,我最喜欢使用 Spring 的方式,因为您可以实现模拟行为:

      @Bean
      private EdocumentDAO getEdocumentDAOMock() {
          return mock(EdocumentDAO.class);
      }
      

      另外,由于你使用的是Spring,所以不能使用new A(),你必须使用Spring来实例化一个Bean,否则autowired注解不起作用。

      【讨论】:

      • 您好,感谢您的回复。我试过模拟 EDocumentDAO,当我模拟时我失去了保存功能,这意味着 save() 不起作用。为此我使用了 derby DB。
      • 你应该隔离你的测试。对 DAO 进行测试,对文档创建者进行测试。所以确实,save 方法不应该在你的测试中工作,这是一个很好的做法。
      【解决方案3】:

      你可以使用mockito的简写注入,而不是依赖Spring这个:

      class ATest {
          @Rule public MockitoRule mockitoRule = MockitoJUnit.rule();
          @Mock EdocumentDAO dao;
          @InjectMocks A a;
      
          @Test
          public void the_test() {
              doReturn("DOC_ID").when(dao).saveIndocRepo();
              a.createDocument(docType);
          }
      }
      

      注意这是伪代码,因为我现在不能使用 IDE

      【讨论】:

      • 感谢 Brice 的快速响应,我尝试按照您的建议进行创建。但不幸的是,出现了这个错误“传递给 when() 的参数不是模拟!”因为实例不是 Mock 类型。另外,我正在使用 IN-Memory derby db 测试 DAO 功能。 Mocking DAO 会锻炼吗?
      • 是的,从您的问题代码中复制粘贴,它不应该是a,而是dao(这是实际的模拟)。我更新了答案。
      猜你喜欢
      • 2011-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-08-02
      • 2019-12-09
      • 1970-01-01
      相关资源
      最近更新 更多