How to write JUnit test with Spring Autowire?

137,447

Solution 1

Make sure you have imported the correct package. If I remeber correctly there are two different packages for Autowiring. Should be :org.springframework.beans.factory.annotation.Autowired;

Also this looks wierd to me :

@ContextConfiguration("classpath*:conf/components.xml")

Here is an example that works fine for me :

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/applicationContext_mock.xml" })
public class OwnerIntegrationTest {

    @Autowired
    OwnerService ownerService;

    @Before
    public void setup() {

        ownerService.cleanList();

    }

    @Test
    public void testOwners() {

        Owner owner = new Owner("Bengt", "Karlsson", "Ankavägen 3");
        owner = ownerService.createOwner(owner);
        assertEquals("Check firstName : ", "Bengt", owner.getFirstName());
        assertTrue("Check that Id exist: ", owner.getId() > 0);

        owner.setLastName("Larsson");
        ownerService.updateOwner(owner);
        owner = ownerService.getOwner(owner.getId());
        assertEquals("Name is changed", "Larsson", owner.getLastName());

    }

Solution 2

I've done it with two annotations for test class: @RunWith(SpringRunner.class) and @SpringBootTest. Example:

@RunWith(SpringRunner.class )
@SpringBootTest
public class ProtocolTransactionServiceTest {

    @Autowired
    private ProtocolTransactionService protocolTransactionService;
}

@SpringBootTest loads the whole context, which was OK in my case.

Solution 3

A JUnit4 test with Autowired and bean mocking (Mockito):

// JUnit starts with spring context
@RunWith(SpringRunner.class)
// spring loads context configuration from AppConfig class
@ContextConfiguration(classes = AppConfig.class)
// overriding some properties with test values if you need
@TestPropertySource(properties = {
        "spring.someConfigValue=your-test-value",
})
public class PersonServiceTest {

    @MockBean
    private PersonRepository repository;

    @Autowired
    private PersonService personService; // uses PersonRepository    

    @Test
    public void testSomething() {
        // using Mockito
        when(repository.findByName(any())).thenReturn(Collection.emptyList());
        Person person = new Person();
        person.setName(null);

        // when
        boolean found = personService.checkSomething(person);

        // then
        assertTrue(found, "Something is wrong");
    }
}

Solution 4

In Spring 2.1.5 at least, the XML file can be conveniently replaced by annotations. Piggy backing on @Sembrano's answer, I have this. "Look ma, no XML".

It appears I to had list all the classes I need @Autowired in the @ComponentScan

@RunWith(SpringJUnit4ClassRunner.class)
@ComponentScan(
    basePackageClasses = {
            OwnerService.class
            })
@EnableAutoConfiguration
public class OwnerIntegrationTest {
    
    @Autowired
    OwnerService ownerService;
    
    @Test
    public void testOwnerService() {
       Assert.assertNotNull(ownerService);
    }
}
Share:
137,447
Premraj
Author by

Premraj

Updated on July 29, 2022

Comments

  • Premraj
    Premraj almost 2 years

    Here are the files that I use:

    component.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" xmlns:context="http://www.springframework.org/schema/context"
        xmlns:jee="http://www.springframework.org/schema/jee"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
             http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
             http://www.springframework.org/schema/context
             http://www.springframework.org/schema/context/spring-context-3.0.xsd 
             http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd">
    
        <context:component-scan
            base-package="controllers,services,dao,org.springframework.jndi" />
    </beans>
    

    ServiceImpl.java

    @org.springframework.stereotype.Service
    public class ServiceImpl implements MyService {
    
        @Autowired
        private MyDAO myDAO;
    
        public void getData() {...}    
    }
    

    ServiceImplTest.java

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration("classpath*:conf/components.xml")
    public class ServiceImplTest{
    
        @Test
        public void testMyFunction() {...}
    }
    

    Error:

    16:22:48.753 [main] ERROR o.s.test.context.TestContextManager - Caught exception while allowing TestExecutionListener [org.springframework.test.context.support.DependencyInjectionTestExecutionListener@2092dcdb] to prepare test instance [services.ServiceImplTest@9e1be92]
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'services.ServiceImplTest': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private services.ServiceImpl services.ServiceImplTest.publishedServiceImpl; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [services.ServiceImpl] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:287) ~[spring-beans.jar:3.1.2.RELEASE]