Java 如何在内部测试类中注入spring上下文?或者还有什么其他的解决办法?
我有一个测试类,它的结构应该是内部/嵌套类。一个家伙建议我使用Java 如何在内部测试类中注入spring上下文?或者还有什么其他的解决办法?,java,spring,junit,Java,Spring,Junit,我有一个测试类,它的结构应该是内部/嵌套类。一个家伙建议我使用@RunWith(hierarchycalcontextrunner.class)来运行它。从我的跑步者那里 已经试过了,我更喜欢这个,我想继续使用它。我已经根据这个建议建立了我的班级。它在外部类中运行良好,内部的所有测试都运行良好。但内部类中的所有内容都会引发这样的问题: IllegalStateException: Failed to load ApplicationContext ... Caused by: java.lang
@RunWith(hierarchycalcontextrunner.class)
来运行它。从我的跑步者那里
已经试过了,我更喜欢这个,我想继续使用它。我已经根据这个建议建立了我的班级。它在外部类中运行良好,内部的所有测试都运行良好。但内部类中的所有内容都会引发这样的问题:
IllegalStateException: Failed to load ApplicationContext
...
Caused by: java.lang.IllegalStateException: Neither GenericXmlContextLoader nor AnnotationConfigContextLoader was able to load an ApplicationContext from [MergedContextConfiguration@4aa22cc2 testClass = AbstractBaseEntityGenericDao_Test.Find_Method, locations = '{}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextCustomizers = set[[empty]], contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]].
MyTestClass:
@ActiveProfiles(profiles = "test")
@RunWith(HierarchicalContextRunner.class)
@ContextConfiguration(classes = {
PersistenceConfig.class,
RootConfig.class })
@WebAppConfiguration
@Transactional
@Rollback
public class AbstractBaseEntityGenericDao_Test {
private static final String[] CUSTOMER_NAMES = {"Veronica", "Hanna", "Eric"};
@ClassRule
public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule();
@Rule
public final SpringMethodRule springMethodRule = new SpringMethodRule();
@Autowired
private ApplicationContext applicationContext;
@Autowired
private SessionFactory sessionFactory;
@Rule
public ExpectedException thrown = ExpectedException.none();
private AbstractClassStub abstractClassStub;
private class AbstractClassStub extends AbstractBaseEntityGenericDao<NamedStubEntity> {
public AbstractClassStub(SessionFactory sessionFactory) {
setClassInstance(NamedStubEntity.class);
this.sessionFactory = sessionFactory;
}
@Override
public void create(NamedStubEntity entity) {
super.create(entity);
}
@Override
public Optional find(Long id) {
return super.find(id);
}
@Override
public void update(NamedStubEntity entity) {
super.update(entity);
}
@Override
public void remove(@NonNull Long id) throws EntityNotFoundException {
super.remove(id);
}
@Override
public void remove(NamedStubEntity entity) {
super.remove(entity);
}
}
@Before
public void setUp() throws Exception {
abstractClassStub = new AbstractClassStub(sessionFactory);
DbTestUtil.resetAutoIncrementColumns(applicationContext, "base_stub_entity");
//...
}
@After
public void tearDown() throws Exception {
//...
}
@Test
public void find_outer_test() {
//Successful
}
public class Find_Method {
@Test
public void find_must_return_entity_in_database_by_id() {
//Unsuccessful
}
@Test
public void find_must_throw_NullPointerException() {
//Unsuccessful
}
@Test
public void find_should_return_BaseStubEntity() {
//Unsuccessful
}
} }
AbstractBaseEntityGenericDao_测试
@ActiveProfiles(profiles = "test")
@RunWith(HierarchicalContextRunner.class)
public class AbstractBaseEntityGenericDao_Test extends AbstractSpringTest {
private AbstractClassStub abstractClassStub;
private class AbstractClassStub extends AbstractBaseEntityGenericDao<NamedStubEntity> {
public AbstractClassStub(SessionFactory sessionFactory) {
setClassInstance(NamedStubEntity.class);
this.sessionFactory = sessionFactory;
}
@Override
public void create(NamedStubEntity entity) {
super.create(entity);
}
//...
}
@Before
public void setUp() throws Exception {
abstractClassStub = new AbstractClassStub(sessionFactory);
DbTestUtil.resetAutoIncrementColumns(applicationContext, "base_stub_entity");
//...
}
@After
public void tearDown() throws Exception {
//...
}
@Test
public void find_must_find() {
//Successful
}
public class Find_Method extends AbstractSpringTest {
@Test
public void find_must_throw_NullPointerException() {
//Unsuccessful
}
@Test
public void find_should_return_BaseStubEntity() {
//Unsuccessful
}
}
}
@ActiveProfiles(profiles=“test”)
@RunWith(HierarchycalContextRunner.class)
公共类AbstractBaseEntityGenericDao_测试扩展了AbstractSpringTest{
私有抽象类存根抽象类存根;
私有类AbstractClassStub扩展了AbstractBaseEntityGenericDao{
公共抽象类存根(SessionFactory SessionFactory){
setClassInstance(namedSubEntity.class);
this.sessionFactory=sessionFactory;
}
@凌驾
公共void创建(namedSubEntity){
超级创建(实体);
}
//...
}
@以前
public void setUp()引发异常{
abstractClassStub=新的abstractClassStub(sessionFactory);
resetAutoIncrementColumns(applicationContext,“base_stub_entity”);
//...
}
@之后
public void tearDown()引发异常{
//...
}
@试验
public void find_must_find(){
//成功的
}
公共类Find_方法扩展了AbstractSpringTest{
@试验
public void find_must_throw_NullPointerException(){
//不成功
}
@试验
public void find_应_返回_BaseStubEntity(){
//不成功
}
}
}
它在调试器中的外观。调试器甚至不进入内部方法。它停在班级一级
我曾尝试将内部类设置为静态,以使其在外部可见,但
HierarchycalContextRunner
停止查看嵌套类中的测试方法。您已经非常接近了。事实上,您的方法甚至可能是正确的,因为问题与配置文件有关,而不是与测试本身有关
广义地说,最简单的方法是将相关注释也放在嵌套类上,我认为这是您想要避免的
使其更干净的一种方法是让您的测试类都继承自一个公共类。然后,带注释的类将成为公共类。这对我来说尤其有效,因为我甚至不必在每次测试中编写所有不同的Spring注释。
这将要求您将@ClassRule
和@Rule
注释与SpringClassRule
和SpringMethodRule
和@RunWith(Enclosed.class)
或类似内容结合使用。。。就像你已经在做的那样
在您的情况下,Find_方法
类必须从AbstractSpringTest
类继承,而该类又将使用@WebAppConfiguration
和相关注释进行注释。但是请注意,Find_方法
类应声明为static
以下是此类设置的部分摘录:
package mypackage;
import org.junit.Rule;
import org.springframework.test.context.junit4.rules.SpringMethodRule;
import org.junit.ClassRule;
import org.springframework.test.context.junit4.rules.SpringClassRule;
import ...
@WebAppConfiguration
@ContextConfiguration(classes = { TestConfigurationClass1.class, TestConfigurationClass2.class })
public class AbstractSpringTest {
@Rule
public final SpringMethodRule springMethodRule = new SpringMethodRule();
@ClassRule
public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule();
}
@RunWith(Enclosed.class)
public class MyTestClass extends AbstractSpringTest {
...
public static class MyNestedTestClass extends AbstractSpringTest {
...
}
public static class MyOtherNestedTestClass extends AbstractSpringTest {
...
}
}
下面是您的测试类的外观:
package mypackage;
import org.junit.Rule;
import org.springframework.test.context.junit4.rules.SpringMethodRule;
import org.junit.ClassRule;
import org.springframework.test.context.junit4.rules.SpringClassRule;
import ...
@WebAppConfiguration
@ContextConfiguration(classes = { TestConfigurationClass1.class, TestConfigurationClass2.class })
public class AbstractSpringTest {
@Rule
public final SpringMethodRule springMethodRule = new SpringMethodRule();
@ClassRule
public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule();
}
@RunWith(Enclosed.class)
public class MyTestClass extends AbstractSpringTest {
...
public static class MyNestedTestClass extends AbstractSpringTest {
...
}
public static class MyOtherNestedTestClass extends AbstractSpringTest {
...
}
}
不用说,使用“规则”可以让您拥有任何您认为适合您的目的的@RunWith
注释。在我的例子中,我发现使用这种方法来运行参数化测试非常有用
但是,您描述的错误似乎指向加载相关配置文件时出现的问题(
application.properties
、application context.xml
及类似文件)。一般建议是仔细检查所有配置文件是否位于类路径的正确路径上,以供测试使用。请注意,这意味着,例如,检查目标
目录的内容,以及排除IDE“发脾气”和拒绝适当管理特定资源的情况,最好的方法是运行mvn干净安装
谢谢您的解决方案。它在内部类中抛出“NoSuchBeanDefinitionException:No'org.hibernate.SessionFactory'类型的限定bean”,外部类中的所有内容似乎都在工作。我已经将@Autowired字段删除到抽象类中,但仍然得到相同的异常。在调试器中,所有字段(SessionFactory、ApplicationContext、SpringMethodRule)均为空。在调试器中,内部类中的SpringMethodRule显示以下内容:((AbstractBaseEntityGenericDao_测试)this)。SpringMethodRule=不可转换类型;无法将'com.初学者课程.softcomputer.abstractions.persistence.dao.AbstractBaseEntityGenericDao_Test.Find_Method'强制转换为'com.初学者课程.softcomputer.abstractions.persistence.dao.AbstractBaseEntityGenericDao_Test'。请提供修改后的代码,以便我可以查看。与我的代码相比,我可以看到两个不同之处。不确定是不是这些问题,但值得一试,即使只是为了消除这些问题的根源。尝试将HierarchycalContextRunner
替换为封闭的
,并使两个嵌套的测试类成为静态的
。如果可行,试着逐一重新介绍。如果它们不起作用,请在这里再次发表评论,我们将继续。我目前的猜测是,它无法加载其中一个或多个文件。验证它们相对于JUnit的路径,以确保它们位于预期位置。我偶尔发现有必要进行mvn清理安装
,因为IDE并不总是复制这些文件,即使它应该这样做。通常,确保配置文件在运行时位于测试预期的位置。