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?
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.
Comments