Springs @Autowiring 功能以及 Mocking
Springs @Autowiring functionality Along with Mocking
问题:
我有一个 class 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_Testclass
@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()
中调用,模拟值应该是 returned.After 收到 DocID,其他文档详细信息保存到数据库中(为此我配置了 Derby In-内存数据库)。 EdocumentDAO 在由弹簧实例化的自动装配上工作。
问题:
当我尝试模拟方法(saveInDocRepo)时,它的模拟成功但自动装配失败。这导致 JUnit 失败。
当我删除模拟时,自动装配正在完美执行。
有没有我遗漏的东西。还是我的做法不对。
专家-请指教一个合适的解决方案。
您必须模拟接口而不是 Class 本身。
使用 Class 的 public 方法创建接口以模拟。
在上面的示例中,您正在监视 A
,但 A
取决于 EdocumentDAO
。你也必须模拟这个 Class。
@Mock
EdocumentDAO edocumentDAOMock;
或者,我最喜欢 Spring 的方式,因为您可以实现模拟行为:
@Bean
private EdocumentDAO getEdocumentDAOMock() {
return mock(EdocumentDAO.class);
}
另外,由于你使用的是Spring,所以不能使用new A()
,必须使用Spring来实例化一个Bean,否则autowired annotation将无法使用.
您可以使用 mockito 的 shorthand 注入而不依赖于 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
谢谢大家的帮助。
解决方案:
@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() 被模拟为 return "DOC_ID" 并且 eDocumentDAO.save() 完美运行。
它的@Spy 用于部分模拟,挽救了这一天。
问题: 我有一个 class 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_Testclass
@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()
中调用,模拟值应该是 returned.After 收到 DocID,其他文档详细信息保存到数据库中(为此我配置了 Derby In-内存数据库)。 EdocumentDAO 在由弹簧实例化的自动装配上工作。
问题: 当我尝试模拟方法(saveInDocRepo)时,它的模拟成功但自动装配失败。这导致 JUnit 失败。 当我删除模拟时,自动装配正在完美执行。
有没有我遗漏的东西。还是我的做法不对。 专家-请指教一个合适的解决方案。
您必须模拟接口而不是 Class 本身。 使用 Class 的 public 方法创建接口以模拟。
在上面的示例中,您正在监视 A
,但 A
取决于 EdocumentDAO
。你也必须模拟这个 Class。
@Mock
EdocumentDAO edocumentDAOMock;
或者,我最喜欢 Spring 的方式,因为您可以实现模拟行为:
@Bean
private EdocumentDAO getEdocumentDAOMock() {
return mock(EdocumentDAO.class);
}
另外,由于你使用的是Spring,所以不能使用new A()
,必须使用Spring来实例化一个Bean,否则autowired annotation将无法使用.
您可以使用 mockito 的 shorthand 注入而不依赖于 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
谢谢大家的帮助。
解决方案:
@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() 被模拟为 return "DOC_ID" 并且 eDocumentDAO.save() 完美运行。 它的@Spy 用于部分模拟,挽救了这一天。