Why spring can't find my bean?

Freewind

I created an interface and a class:

public interface UserService {
    List<User> listAll();
}

@Transactional
public class DefaultUserService implements UserService {
    private String tableName;
    public List<User> listAll() { someDao.listAllFromTable(tableName); }
    public void setTableName(String tableName) { this.tableName = tableName; }
}

Also in my application context xml file context.xml, I defined:

<bean id="userService" class="mypackage.DefaultUserService">
    <property name="tableName" value="myusers" />
</bean>

Then I want to test the DefaultUserService:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:context-test.xml"})
@TransactionConfiguration(transactionManager = "testTransactionManager")
@Transactional
public class UserServiceTest {

    @Autowired
    private DefaultUserService userService;

    @Before
    public void setup() {
        userService.setTableName("mytesttable");
    }
    @Test
    public void test() {
        // test with userService;
        userService.listAll();
    }
}

Notice it uses context-test.xml, which imported the original context.xml:

<import resource="classpath:context.xml"/>

Unfortunately, when the test starts, spring throws exception:

org.springframework.beans.factory.BeanCreationException: 
Error creating bean with name 'mypackage.UserServiceTest': 
Injection of autowired dependencies failed; 
nested exception is org.springframework.beans.factory.BeanCreationException: 
Could not autowire field: 
private mypackage.DefaultUserService mypackage.userService

nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: 
No qualifying bean of type [mypackage.DefaultUserService] 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)}

I'm not sure where is wrong, why spring can't find the bean DefaultUserService I defined?

Boris Treukhov

It's because @Transactional places the bean is behind a jdk proxy implementing UserService interface, after that the bean is only available as UserService and not DefaultUserService. See https://stackoverflow.com/a/18875681/241986.

You can try setting the table name with a property placeholder @Value("${someprop}") and define that property in test context, or create another interface that will expose setTableName(), and autowire that helper interface into the test case.

I'm not sure there are any easy solutions of the problem, I think this task can be subsumed under the problem of bean redefinition in Spring test-context framework Spring beans redefinition in unit test environment

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related