5

I am new to spring boot. Need some suggestions Here my unit test class

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = DemoApplication.class)
public class EmployeeRepositoryTest {

@Autowired
protected EmployeeRepository employeeRepository;


@Test
public void insertEmploee(){

    Employee employee = new Employee();

    employee.setEmpName("Azad");
    employee.setEmpDesignation("Engg");
    employee.setEmpSalary(12.5f);

    employeeRepository.save(employee);

}

}

When I run it I get exception as

java.lang.NoSuchMethodError: org.springframework.core.annotation.AnnotatedElementUtils.findMergedAnnotationAttributes(Ljava/lang/reflect/AnnotatedElement;Ljava/lang/String;ZZ)Lorg/springframework/core/annotation/AnnotationAttributes;

at org.springframework.test.util.MetaAnnotationUtils$AnnotationDescriptor.<init>(MetaAnnotationUtils.java:290)
at org.springframework.test.util.MetaAnnotationUtils$UntypedAnnotationDescriptor.<init>(MetaAnnotationUtils.java:365)
at org.springframework.test.util.MetaAnnotationUtils$UntypedAnnotationDescriptor.<init>(MetaAnnotationUtils.java:360)
at org.springframework.test.util.MetaAnnotationUtils.findAnnotationDescriptorForTypes(MetaAnnotationUtils.java:191)
at org.springframework.test.util.MetaAnnotationUtils.findAnnotationDescriptorForTypes(MetaAnnotationUtils.java:198)
at 

Process finished with exit code -1

Saiful Azad
  • 1,823
  • 3
  • 17
  • 27
  • 6
    Looks like a problem with your dependencies (maybe you are mixing some Spring-Versions). Could you provide your dependencies (pom.xml if you are using maven or the equivalent gradle-file)? – Mike Boddin Feb 17 '16 at 09:29
  • @MikeBoddin It is solved. you r correct – Saiful Azad Feb 17 '16 at 09:30
  • 1
    BTW, if you are starting Spring context in your test, it's mostly not considered as unit test anymore. – luboskrnac Feb 17 '16 at 11:44
  • @luboskrnac I am interested to know more details – Saiful Azad Feb 17 '16 at 12:07
  • 2
    Just the naming/title is wrong, this is more an integration test than an actual unit test. For unit tests (when you simply need to test some piece of code), it's probably not a good idea to use the `SpringJUnit4ClassRunner` runner, because it starts the entire application and is a lot slower than using no runner. In this case you're probably going to check if the record was created on the database, in this case you're writing an integration test. – g00glen00b Feb 17 '16 at 12:15

2 Answers2

2

It seems that your problem is solved (mixing the Spring dependency versions) but let me just expand the comment from @g00glen00b on how to write unit tests.

Make sure the following dependency is in your pom.xml:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

As pointed out in the comment, @RunWith(SpringJUnit4ClassRunner.class) causes the unit test to start the whole application and it is used rather for integration testing.

Fortunately, Spring-boot has built in dependency for Mockito which is just what you need for unit tests like this.

Now, your unit test could look something like this:

public class EmployeeRepositoryTest {

@InjectMocks
private EmployeeRepository employeeRepository;

@Mock
private Something something; // some class that is used inside EmployRepository (if any) and needs to be injected

@Before
public void setUp() {
    MockitoAnnotations.initMocks(this);
}

@Test
public void insertEmploee(){

    Employee employee = new Employee();

    employee.setEmpName("Azad");
    employee.setEmpDesignation("Engg");
    employee.setEmpSalary(12.5f);

    employeeRepository.save(employee);

    Mockito.verify(...); // verify what needs to be verified
    }
}

Nice post about using Mockito can be found, for example, here.

Smajl
  • 7,555
  • 29
  • 108
  • 179
  • Cannot instantiate InjectMocks field named 'employeeRepository'. You haven't provided the instance at field declaration so I tried to construct the instance. However, I failed because: the type 'EmployeeRepository' is an interface. Examples of correct usage of InjectMocks: InjectMocks Service service = new Service(); InjectMocks Service service; – Saiful Azad Feb 19 '16 at 08:57
  • I did not know that this is a Spring JPA Repository (although is should have been obvious from the name). In that case, it actually is an integration test and your initial attempt was correct. My post applies mainly to classes that needs to be instantiated. It might help you with some other unit tests. Spring repositories do not have to be unit tested (they already are in Spring). You can only perform integration testing with them. Hope it makes sense – Smajl Feb 19 '16 at 09:00
  • This might be a useful reading: http://stackoverflow.com/questions/23435937/how-to-test-spring-data-repositories – Smajl Feb 19 '16 at 09:02
0

Instead of using @Autowired on EmployeeRepository we can use @MockBean cause we are writing unit tests we don't need to deal with the real data we just need to verify that the function is working fine or not. Check the below code

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = Main.class)//main springboot class
@WebAppConfiguration
public abstract class AbstractBaseTest {
   protected MockMvc mvc;
   @Autowired
   WebApplicationContext webApplicationContext;

   protected void setUp() {
      mvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
   }

}    

public class EmployeeRepositoryTest extends AbstractBaseTest{

@MockBean
protected EmployeeRepository employeeRepository;

 @Override
   @Before
   public void setUp() {
      super.setUp();
   }

@Test
public void insertEmploee(){

    Employee employee = new Employee();

    employee.setEmpName("Azad");
    employee.setEmpDesignation("Engg");
    employee.setEmpSalary(12.5f);

       Mockito.doNothing().when(employeeRepository).save(Mockito.any(Employee.class));
       employeeRepository.save(employee);
       Mockito.verify(employeeRepository, Mockito.times(1)).save(employee);

}
}
abhinav kumar
  • 1,487
  • 1
  • 12
  • 20