我的问题与向Spring bean中注入mock mock中提出的问题非常相似。事实上,我相信公认的答案可能对我有用。然而,我对这个答案有一个问题,然后再做一些进一步的解释,以防这个答案实际上不是我的答案。
所以我按照前面提到的链接找到了Springockito的网站。我修改了我的test-config.xml
,以包含类似于以下内容:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mockito="http://www.mockito.org/spring/mockito"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.mockito.org/spring/mockito http://www.mockito.org/spring/mockito.xsd">
...
<mockito:mock id="accountService" class="org.kubek2k.account.DefaultAccountService" />
...
</beans>
目前www.mockito.org
重定向似乎有问题,所以我在https://bitbucket.org/kubek2k/springockito/raw/16143b32095b/src/main/resources/spring/mockito.xsd找到了XSD代码,并更改了xsi:schemaLocation中的最后一个条目,以指向这个位桶链接。
运行mvn test
会产生以下错误(为了可读性添加了换行符):
Caused by: org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException:
Line 43 in XML document from class path resource [spring/test-context.xml] is invalid;
nested exception is org.xml.sax.SAXParseException; lineNumber: 43; columnNumber: 91;
The prefix "mockito" for element "mockito:mock" is not bound.
所以关于Springockito的问题是:是否有可能再包含这个?我错过了什么?
现在,进一步解释…
我有一个接口,我想测试它的实现:
public interface MobileService {
public Login login(Login login);
public User getUser(String accessCode, Date birthDate);
}
实现包含了Spring @Autowire
为我提供的DAO:
@Service
public class MobileServiceImpl implements MobileService {
private MobileDao mobileDao;
@Autowired
public void setMobileDao(MobileDao mobileDao) {
this.mobileDao = mobileDao;
}
}
我不想改变我的接口来包含setMobileDao
方法,因为那将只是添加代码来支持我的单元测试。我试图模拟DAO,因为这里的实际SUT是ServiceImpl。我怎样才能做到这一点呢?
您不想测试您的接口:它根本不包含任何代码。您想要测试您的实现。setter是可用的。就用它吧:
@Test
public void testLogin() {
MobileServiceImpl toTest = new MobileServiceImpl();
toTest.setMobileDao(mockMobileDao);
// TODO call the login method and check that it works as expected.
}
不需要spring上下文。只需实例化您的POJO服务,手动注入模拟依赖,并测试您想要测试的方法。
在与springckitto XSD问题斗争了一段时间后,我发现了一个更简单的解决方案。让Spring使用工厂方法为您注入mock,即在applicationContext.xml中put:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="com.gerrydevstory.mycoolbank.AccountsDAO"/>
</bean>
<bean class="com.gerrydevstory.mycoolbank.BankingService"/>
</beans>
将AccountsDAO bean注入到BankingService类中。对应的JUnit测试用例是:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/BankingServiceTest.xml")
public class BankingServiceTest {
@Autowired private BankingService bankingService;
@Autowired private AccountsDAO mockAccountsDAO;
@Test
public void testTransfer() throws Exception {
// Setup 2 accounts
Account acc1 = new Account();
acc1.setBalance(800.00);
Account acc2 = new Account();
acc2.setBalance(200.00);
// Tell mock DAO to return above accounts when 1011 or 2041 is queried respectively
when(mockAccountsDAO.findById(1011)).thenReturn(acc1);
when(mockAccountsDAO.findById(2041)).thenReturn(acc2);
// Invoke the method to test
bankingService.transfer(1011, 2041, 500.00);
// Verify the money has been transferred
assertEquals(300.00, acc1.getBalance(), 0.001);
assertEquals(700.00, acc2.getBalance(), 0.001);
}
}
我个人觉得这很优雅,很容易理解。
设置模拟dao有三个选项:
- 测试实现—它通过setDao方法为mock提供了一个接缝。(作为JB的回答)
- 将setDao方法添加到接口—不希望这样做,因为您不想仅仅为了支持测试而添加代码。
- 在impl类中添加一个构造函数以接受dao -不需要的原因与#2相同。
如果你想做#3,你需要给MobileService添加一个构造函数,让它接受MobileDao。
public MobileServiceImpl(MobileDao mobileDao) {
this.mobileDao = mobileDao;
}
那么你的测试将看起来像这样:
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.*;
import java.util.Date;
import org.junit.Before;
import org.junit.Test;
public class MobileServiceImplTest {
private MobileService systemUnderTest;
private MobileDao mobileDao;
@Before
public void setup() {
mobileDao = mock(MobileDao.class);
systemUnderTest = new MobileServiceImpl(mobileDao);
}
@Test
public void testGetUser() {
//if you need to, configure mock behavior here.
//i.e. when(mobileDao.someMethod(someObject)).thenReturn(someResponse);
systemUnderTest.getUser("accessCode", new Date());
verify(mobileDao).getUser("JeffAtwood");
}
}
请注意,您没有向我们提供MobileDao的详细信息,因此我创建了一个getUser方法,该方法接受一个String。
要使测试通过,您的MobileServiceImpl只需要这样:
mobileDao.getUser("JeffAtwood");
问题似乎是你的类路径不包含实际的springckito jar -你不必更改URL -这些只是spring内部使用的令牌-它们没有被解决-所有你需要的是一个足够新的spring发行版和springckito在类路径上。
Kuba(前面提到的lib的创建者:))
我有同样的问题,我想使用springckito根据他们的wiki,但验证xml抛出错误。所以当我试着去xsd应该在的地方时,它没有。所以我读了这个,并开始使用这个:
xmlns:mockito="http://www.mockito.org/spring/mockito"
xsi:schemaLocation="http://www.mockito.org/spring/mockito
https://bitbucket.org/kubek2k/springockito/raw/16143b32095b/src/main/resources/spring/mockito.xsd">
但是当我看到这个链接,有不好的感觉。在我看来,这不是永久稳定的链接(你必须检查如果我错了)