这个问题在这里已有答案:
问题摘要:
在常规运行期间(使用@Autowired
)成功创建配置对象,但在单元测试阶段运行时是null
。
编辑,以回应将问题标记为重复:我不认为这是Why is my Spring @Autowired field null?的重复,因为我的问题是关于单元测试阶段,而上述问题是关于常规运行阶段。
详细:
我有一个读取属性文件的配置对象:
@Configuration
@ConfigurationProperties(prefix = "defaults")
@Getter
@Setter
public class DefaultsConfigProperties {
Double value;
....
在服务层中,我在常规模式下运行应用程序时成功使用此类:
@Service
@Configuration
public class CatsService {
@Autowired
DefaultsConfigProperties defaultsConfigProperties;
...
然而,问题是在单元测试期间,因为defaultsConfigProperties
是null
。
这是测试类:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
@TestPropertySource(properties = {
"defaults.value=0.2"
})
public class CatServiceTest {
private CatService;
@Before
public void before(){
catService = new CatService();
}
如果我理解正确,我需要在单元测试阶段以某种方式创建/注入/模拟DefaultsConfigProperties
类。
我也知道不推荐使用@Autowired
,最好将项目传递给类的构造函数。所以,如果解决方案是CatService
需要接受构造函数中的DefaultsConfigProperties
,然后在CatServiceTest
中创建它(如何?)?
@SpringBootTest
注释采用classes
数组参数。您可以将使用@Configuration
注释的任何类传递到此数组中,如果要加载相同的SpringApplication.run(...)
,还可以传递包含主方法(ApplicationContext
)的类。在你的情况下:
@SpringBootTest(classes = {Application.class, DefaultsConfigProperties.class})
请注意,您也可以直接使用SpringRunner
。
你是在正确的轨道上,正如你所说的那样,构造注入在场注入之上是有利的。
然而,如果你想依靠现场注入你可以使用Mockito
。
在单元测试中使用的示例:
@Mock
DefaultsConfigProperties defaultsConfigProperties;
@InjectMocks
private CatService;
@Before
public void before(){
catService = new CatService();
MockitoAnnotations.init(this);
}
因此,在您的情况下,您还应删除测试类的注释以使其成为单元测试。