Spring + Mockito Injection

My question is very similar to the question raised in Injecting Mockito mocking Spring bean . In fact, I believe that the accepted answer can really work for me. However, I have one problem with the answer, and then some further explanation in case the answer is not really my answer.

So, I followed the link in the above post on the Springockito website. I modified my test-config.xml to include something similar to the following:

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

There seems to be something wrong with the redirect to www.mockito.org currently, so I found the XSD code at https://bitbucket.org/kubek2k/springockito/raw/16143b32095b/src/main/resources/spring/mockito. xsd and changed the final entry in xsi: schemaLocation to point to this bitbucket link.

Running mvn test then produced the following error (new lines added for reading):

 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. 

So the question about Springockito: is it possible to enable this? What am I missing?

Now, for a further explanation ...

I have an interface whose implementation I'm trying to check:

 public interface MobileService { public Login login(Login login); public User getUser(String accessCode, Date birthDate); } 

The implementation contains a DAO for Spring @Autowire for me:

 @Service public class MobileServiceImpl implements MobileService { private MobileDao mobileDao; @Autowired public void setMobileDao(MobileDao mobileDao) { this.mobileDao = mobileDao; } } 

I do not want to change my interface to include the setMobileDao method, because it will be adding code only to support my unit testing. I am trying to mock the DAO, since the actual SUT here is ServiceImpl. How can I achieve this?

+6
source share
5 answers

You do not want to test your interface: it does not contain code at all. You want to check your implementation. Thus, the setter is available. Just use it:

 @Test public void testLogin() { MobileServiceImpl toTest = new MobileServiceImpl(); toTest.setMobileDao(mockMobileDao); // TODO call the login method and check that it works as expected. } 

No spring context needed. Just install your POJO service, manually enter the layout dependencies and check the methods you want to test.

+9
source

After a short struggle with the Springockito XSD problem, I found a much simpler solution. Let Spring introduce the layout for you using the factory method, i.e. in 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> 

where AccountsDAO bean is introduced into the BankingService class. Relevant JUnit test case:

 @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); } } 

Personally, I find it very elegant and easy to understand. For more information, see the original blog post .

+1
source

You have three options for setting the dao layout:

  • Check implementation - which gives a seam for your layout using the setDao method. (as JB answer)
  • Adding the setDao method to the interface is undesirable since you do not want to add code just to support your tests.
  • Adding a constructor to the impl class to accept dao is not advisable for the same reason as # 2.

If you want to do # 3, you need to add a constructor to MobileService, which accepts MobileDao.

  public MobileServiceImpl(MobileDao mobileDao) { this.mobileDao = mobileDao; } 

Then your test will look like this:

 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. //ie when(mobileDao.someMethod(someObject)).thenReturn(someResponse); systemUnderTest.getUser("accessCode", new Date()); verify(mobileDao).getUser("JeffAtwood"); } } 

Please note that you did not provide us with information about MobileDao, so I created a getUser method that accepts a string.

To pass the test, your MobileServiceImpl just needs:

 mobileDao.getUser("JeffAtwood"); 
0
source

The problem is this: your class path does not contain the actual fan coil - you do not need to change the URL - these are only tokens that are used inside spring - they are not resolved - all you need is a fairly new set of spring and springockito on the way to classes.

Cuba (creator of the above lib :))

0
source

I had the same problem, I wanted to use springockito on their wiki but xml throw error checking. Therefore, when I tried to go to the places where xsd should be, it is not. So I read this and will work with this:

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

But when I watched this link, I had a bad feeling. It seems to me that it is not a permanent stable link (you should check if I am not mistaken)

0
source

Source: https://habr.com/ru/post/899559/


All Articles