Dolphin
Dolphin

Reputation: 38681

No bean named is defined

I am using JUnit to test Component of Spring,throws error:

org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'wsVehicleService' is defined

This is my test class:

package com.zw.ws.service.impl;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ComponentScan;;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:/*.xml")    
public class WsVehicleServiceTest {

    @Autowired
    ApplicationContext ctx;

    @Test
    public void getHistoryAlarmInfo() throws Exception {
        try {
            String requestJson = "\"{\"VEHICLEID\":\"cae21196-cb66-4256-88a6-7cdfb23e2c78\",\"STARTTIME\":1476115200,\"ENDTIME\":1476201599,\"TYPE\":1}\"";
            WsVehicleService vehicleService = (WsVehicleService) ctx.getBean("wsVehicleService");
            vehicleService.getHistoryAlarmInfoImpl(requestJson);
        } catch (BeansException e) {
            e.printStackTrace();
        }
    }
}

This is the class will be tested:

@Component
public class WsVehicleService {

    public List<HistoryAlarmInfo> getHistoryAlarmInfo(String requestJson) {
        try {
            return getHistoryAlarmInfoImpl(requestJson);
        } catch (Exception e) {
            log.error(e);
            return null;
        }
    }
}

When JUnit run to getBean,throws error:No bean named 'wsVehicleService' is defined. Where is going wrong?What could I do to make it right?

What I having tried:

add @ComponentScan("com.zw.ws.*") to scan the WsVehicleService class.

This is the log:

    12:53:11.098]-[main]-[org.springframework.test.context.support.AbstractDirtiesContextTestExecutionListener]-{After test method: context [DefaultTestContext@58783f6c testClass = WsVehicleServiceTest, testInstance = com.zw.ws.service.impl.WsVehicleServiceTest@7577b641, testMethod = getHistoryAlarmInfo@WsVehicleServiceTest, testException = org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'wsVehicleService' is defined, mergedContextConfiguration = [MergedContextConfiguration@3a7b503d testClass = WsVehicleServiceTest, locations = '{classpath:/*.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]], class annotated with @DirtiesContext [false] with mode [null], method annotated with @DirtiesContext [false] with mode [null].}

org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'wsVehicleService' is defined

    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:698)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1175)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:284)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1054)
    at com.zw.ws.service.impl.WsVehicleServiceTest.getHistoryAlarmInfo(WsVehicleServiceTest.java:27)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:254)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:89)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:193)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:253)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:84)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)


            12:53:11.107]-[main]-[org.springframework.test.context.support.AbstractDirtiesContextTestExecutionListener]-{After test class: context [DefaultTestContext@58783f6c testClass = WsVehicleServiceTest, testInstance = [null], testMethod = [null], testException = [null], mergedContextConfiguration = [MergedContextConfiguration@3a7b503d testClass = WsVehicleServiceTest, locations = '{classpath:/*.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]], class annotated with @DirtiesContext [false] with mode [null].}

PS:This is no XML configuration,all beans are using autoscan.

Upvotes: 4

Views: 79714

Answers (6)

yasir abbas
yasir abbas

Reputation: 1

i have make same mistake and just find some simple solution for this issue while calling the getBean method in main class just include the object name which are defined in XML config.

enter image description here

Pass the object Name while calling the getBean;

enter image description here Here Using stu1 in xml file

Upvotes: -1

Rajanboy
Rajanboy

Reputation: 2672

If We are using Component based annotation we have to provide the package path as follows in that configLocation .xml as

<context:component-scan base-package="org.example.javaconfig"/>

which solved my problem

Upvotes: 0

ANiket Chavan
ANiket Chavan

Reputation: 95

Spring Annotation code

//main class    
//@Import(value=AppConfig.class)     
public class AppAnno {   
    public static void main(String[] args) {  
        AnnotationConfigApplicationContext ctx = new  
 AnnotationConfigApplicationContext(AppConfig.class);  
    TodayDate date = ctx.getBean("todayDate",TodayDate.class);   
System.out.println(date.getTodyDate());     
    }     
}    

@Configuration  
@ComponentScan(basePackages={"com.cb.service.anno","com.cb.dao.anno"})  

change it according to your basepackage

public class AppConfig {  
    @Bean 
public Date date(){    
return new Date();   
}    
}  

import java.util.Date;     
import javax.inject.Named;   
import org.springframework.beans.factory.annotation.Autowired;    
import org.springframework.stereotype.Component;   
@Component     
@Named("todayDate")//you have to add inject jar to your build path     
public class TodayDate {      
@Autowired    
    Date date;    
    public String getTodyDate(){     
    return date.toString( );    
    }     
}     

Upvotes: 0

Unknown
Unknown

Reputation: 2137

1)First Solution:

@ContextConfiguration initializes the Spring context and by default looks for a Spring XML file in the same package as the unit test with the file name the same as the class with '-context.xml' as a suffix

Try adding the WsVehicleServiceTest-context.xml file in com.mycompany.annotation package.

<?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 id="wsVehicleService"
          class="com.mycompany.annotation.WsVehicleService">
      </bean>

</beans>

Junit test class after removing ("classpath:/*.xml"):

package com.mycompany.annotation;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class WsVehicleServiceTest {

    @Autowired
    ApplicationContext ctx;

    @Test
    public void getHistoryAlarmInfo() throws Exception {
        try {
            WsVehicleService vehicleService = (WsVehicleService) ctx
                    .getBean("wsVehicleService");
            String hi = vehicleService.sayHi();
            System.out.println(hi);
        } catch (BeansException e) {
            e.printStackTrace();
        }
    }
}

Note: If you want to use @ContextConfiguration("classpath:/*.xml") make sure you put

<bean id="wsVehicleService"
              class="com.mycompany.annotation.WsVehicleService">
</bean>

in any one of your *.xml file

2) Second Solution:

Make sure you put <context:annotation-config /> in your xml file. Here you do not need to declare the wsVehicleService bean in your xml file.

Modify your test class by using @Autowired on WsVehicleService

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:/*.xml")   
public class WsVehicleServiceTest {

    @Autowired
    ApplicationContext ctx;

    @Autowired
    WsVehicleService wsVehicleService;

    @Test
    public void getHistoryAlarmInfo() throws Exception {
        try {
            String hi = wsVehicleService.sayHi();
            System.out.println(hi);
        } catch (BeansException e) {
            e.printStackTrace();
        }
    }
}

3) Third solution:

You have mentioned, you do not use any xml configuration files and your exception tells org.springframework.beans.factory.NoSuchBeanDefinitionException

One reason your WsVehicleService may not exist in the context – is that it may be defined in a package that is not scanned by Spring.

Make sure your WsVehicleService exist in @ComponentScan("com.mycompany.annotation") package.

1) Application configuration class with annotation @Configuration

package com.mycompany.annotation;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;


@Configuration
@ComponentScan("com.mycompany.annotation")
public class AppConfig {

}

2) Your service class

package com.mycompany.annotation;

import org.springframework.stereotype.Component;

@Component
public class WsVehicleService {
    public String sayHi(){
        return "HI !!!!!!!!!!";
    }
}

3)Junit test class

package com.mycompany.annotation;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class)
public class WsVehicleServiceTest {

    @Autowired
    ApplicationContext ctx;

    @Test
    public void getHistoryAlarmInfo() throws Exception {
        try {
            WsVehicleService vehicleService = (WsVehicleService) ctx
                    .getBean("wsVehicleService");
            String hi = vehicleService.sayHi();
            System.out.println(hi);
        } catch (BeansException e) {
            e.printStackTrace();
        }
    }
}

OUTPUT:

HI !!!!!!!!!!

For more info you can refer this and this

More reference for causes and possible solution for NoSuchBeanDefinitionException

Upvotes: 6

exoddus
exoddus

Reputation: 2340

"No bean named 'xxx' is defined" is thrown when:

  • Your bean has a different name.
  • Your bean isn't actually in the context.

Since you haven't changed the default name of the bean, then must be that the bean isn't properly loaded.

You need to indicate where are your components to be scanned (xml config or @Configuration class) and be loaded when run your tests. I would create a config class and then add this new config class in the ContextConfiguration annotation (or use xml if you prefer).

@Configuration
@ComponentScan(basePackages = {"com.zw.ws"})
public class AppTestConfig {}

Your test class then:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={AppTestConfig.class}) 
public class WsVehicleServiceTest {
...
}

You can also anotate with @Autowire your service and let Spring do the wiring work.

Upvotes: 9

kuhajeyan
kuhajeyan

Reputation: 11017

Change line

WsVehicleService vehicleService = (WsVehicleService) ctx.getBean(WsVehicleService .class);

or

@Component("wsVehicleService")
public class WsVehicleService{

//..

}

Upvotes: 6

Related Questions