Spring 弹簧&x2B;莫基托试验注射

Spring 弹簧&x2B;莫基托试验注射,spring,mockito,Spring,Mockito,我的问题与本报告中提出的问题非常相似。事实上,我相信大家接受的答案可能对我有用。然而,我对答案有一个问题,如果答案不是我的答案,我会做进一步的解释 因此,我在上面的帖子中找到了Springockito网站的链接。我修改了我的test config.xml,以包含类似于以下内容的内容: <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSche

我的问题与本报告中提出的问题非常相似。事实上,我相信大家接受的答案可能对我有用。然而,我对答案有一个问题,如果答案不是我的答案,我会做进一步的解释

因此,我在上面的帖子中找到了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>
所以关于Springockito的问题是:是否有可能再包括这个?我错过了什么

现在,关于进一步的解释

我有一个接口,我正在尝试测试它的实现:

public interface MobileService {
    public Login login(Login login);
    public User getUser(String accessCode, Date birthDate);
}
该实现包含一个DAO,Spring
@Autowire
s为我提供:

@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服务,手动注入模拟依赖项,并测试要测试的方法。

您有三个选项来设置模拟dao:

  • 测试实现——它通过setDao方法为您的模拟提供一个接缝。(正如JB的回答)
  • 将setDao方法添加到接口中-不需要,因为您不希望添加代码只是为了支持测试
  • 在impl类中添加一个构造函数以接受dao-与#2的原因不同
  • 如果要执行#3,则需要向接受MobileDao的MobileService添加构造函数

       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方法

    要通过测试,您的MobileServiceImpl只需要以下内容:

    mobileDao.getUser("JeffAtwood");
    

    这个问题看起来好像你的类路径不包含真正的springockito jar-你不必更改URL-这些只是spring内部使用的标记-它们没有得到解决-你所需要的只是一个足够新的spring发行版和类路径上的springockito


    Kuba(前面提到的lib:的创建者)

    我也有同样的问题,我想根据他们的wiki使用springockito,但验证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">
    

    但是当我看到这个链接时,我有一种不好的感觉。在我看来,这不是永久稳定的链接(你必须检查我是否错了)

    在与Springockito XSD问题斗争了一段时间后,我找到了一个更简单的解决方案。让Spring使用工厂方法为您注入模拟,即在applicationContext.xml中:

    <?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>
    

    就我个人而言,我觉得这很优雅,也很容易理解。有关更多详细信息,请参阅。

    @Mike我同意,只需测试实现即可。单元测试没有必要使用spring上下文。顺便说一下,Mockito提供了一些简单的依赖注入机制,它结合了
    @Mock
    @InjectMocks
    注释。您应该看到它们各自的特性。就像向接口添加一个
    setMobileDao
    一样,添加另一个要传入DAO对象的ctor将改变代码以支持单元测试。根据@jb nizet的回答,如果我将测试更改为不使用接口而使用实现,那么我已经可以访问
    setMobileDao
    方法。我明白,您不想仅仅为了支持测试而向代码中添加任何内容。测试impl而不是接口也是我过去做过的;)我只是想给你另一个选择。现在链接好像断了。有人有新的吗?
    <?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>
    
    @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);
      }
    }