Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to access Spring @Service object from jUnit test

Tags:

java

junit

spring

Situation: I have service implementation class annotated with @Service with access to properties file.

@Service("myService")
public class MySystemServiceImpl implements SystemService{

      @Resource
      private Properties appProperties;

}

Properties object is configured through config-file. applicationContext.xml

<util:properties id="appProperties" location="classpath:application.properties"/>

I want to test some methods of this implementation.

Question:How to access MySystemServiceImpl-object from test class in such way that Properties appProperties will be initialized properly?

public class MySystemServiceImplTest {

    //HOW TO INITIALIZE PROPERLY THROUGH SPRING? 
    MySystemServiceImpl testSubject;

    @Test
    public void methodToTest(){
        Assert.assertNotNull(testSubject.methodToTest());
    }     

}

I can't simple create new MySystemServiceImpl - than methods that use appProperties throws NullPointerException. And I can't directly inject properties in the object - there is no appropriate setter-method.

Just put correct steps here (thanks to @NimChimpsky for answer):

  1. I copied application.properties under test/resources dir.

  2. I copied applicationContext.xml under test/resources dir. In application context I add new bean (definition of application properties is already here):

    <bean id="testSubject" class="com.package.MySystemServiceImpl">
    
  3. I modified test class in such way:

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations={"/applicationContext.xml"})
    public class MySystemServiceImplTest {
    
       @Autowired
       MySystemServiceImpl testSubject;
    
    }
    
  4. And this make the trick - now in my test class fully functional object is available

like image 587
dim1902 Avatar asked Oct 11 '11 09:10

dim1902


People also ask

Can we use @value in JUnit?

With the @ValueSource annotation, we can pass an array of literal values to the test method. As we can see, JUnit will run this test two times and each time assigns one argument from the array to the method parameter.

Can we use Autowired in test class?

To check the Service class, we need to have an instance of the Service class created and available as a @Bean so that we can @Autowire it in our test class. We can achieve this configuration using the @TestConfiguration annotation.


2 Answers

Alternatively, to do an integration test I do this.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"/applicationContext-test.xml"})
@Transactional
public class MyTest {

    @Resource(name="myService")
    public IMyService myService;

Then use the service as you would normally. Add the app context to your test/resources directory

like image 80
NimChimpsky Avatar answered Sep 28 '22 05:09

NimChimpsky


Just use its constructor :

MySystemServiceImpl testSubject = new MySystemServiceImpl();

This is a unit test. A unit test tests a class in isolation from the other classes and from the infrastructure.

If your class has dependencies over other interfaces, mock those interfaces and create the object with these mocks as argument. That's the whole point of dependency injection : being able to inject other, mock implementations inside an object in order to test this object easily.

EDIT:

You should provide a setter for your properties object, in order to be able to inject the properties you want for each of the unit tests. The injected properties could contain nominal values, extreme values, or incorrect values depending on what you want to test. Field injection is practical, but doesn't fit well with unit-testing. Constructor or setter injection should be preferred when unit-testing is used, because the main goal of dependency injection is precisely to be able to inject mock or specific dependencies in unit tests.

like image 23
JB Nizet Avatar answered Sep 28 '22 05:09

JB Nizet