Spring 正在测试的 class 中的自动装配依赖项为空
Spring autowired dependency is null in class being tested
我正在尝试为我的 PersonController class 编写单元测试,它使用依赖项 org.modelmapper.ModelMapper
。问题在于,当测试调用使用 ModelMapper 的 PersonController 方法时,ModelMapper 为 null,这会导致错误。很明显,当 运行 测试时它没有被正确地自动连接,但它在 运行 应用程序时工作。我希望有一种方法可以解决这个问题,而无需将 ModelMapper 添加为构造函数参数。
代码片段如下所示:
@SpringBootTest
class PersonControllerTest {
@Mock
private IPersonService personService;
@InjectMocks
private PersonController underTest;
@BeforeEach
void setUp() {
underTest = new PersonController(personService);
}
...Tests...
}
而相关的PersonController代码是:
public class PersonController {
@Autowired
private ModelMapper _modelMapper;
private final IPersonService _personService;
public PersonController (IPersonService personService) {
_personService = personService;
}
...Code that calls _modelMapper...
}
首先你应该用
注释你的class PersonControllerTest
@ExtendWith(SpringExtension.class)
class PersonControllerTest {
或
@ExtendWith(MockitoExtension.class)
class PersonControllerTest {
取决于您的用例。这应该已经解决了您的问题。如果你还在使用 Junit4,你应该使用
@RunWith(Springrunner.class)
class PersonControllerTest {
但是因为你正在使用
@BeforeEach
不应该这样:)
编辑:
当你通过 @Autowired 使用 ModelMapper 时,你必须使用 @ExtendWith(SpringExtension.class) 。您还必须使用 @SpringBootTest 注释您的 class 或使用 @Import 注释手动导入应该通过依赖注入可用的 classes。
这里的一个问题是您正在使用 new PersonController(personService)
手动创建控制器 class,因此 spring 注释 @Autowired
在这里没有任何效果(因为 spring 不是在创建 class 不是在配置它)。
另一个问题是您使用的 mockito @InjectMocks
基本上是注入模拟(用于单元测试),但与此同时,您使用的 @SpringBootTest
用于集成测试(应用程序是正常启动,但处于测试模式)。
根据您的描述,我不清楚您是要编写单元测试还是集成测试。所以:
- 如果您正在编写单元测试代码,请删除
@SpringBootTest
添加 ModelMapper
作为构造函数参数并使用两个模拟实例化 class。
- 如果您正在编写 spring integration test,请删除
@InjectMocks
和 class 的手动 class 实例化,并在测试中将控制器标记为 @Autowire
。
我正在尝试为我的 PersonController class 编写单元测试,它使用依赖项 org.modelmapper.ModelMapper
。问题在于,当测试调用使用 ModelMapper 的 PersonController 方法时,ModelMapper 为 null,这会导致错误。很明显,当 运行 测试时它没有被正确地自动连接,但它在 运行 应用程序时工作。我希望有一种方法可以解决这个问题,而无需将 ModelMapper 添加为构造函数参数。
代码片段如下所示:
@SpringBootTest
class PersonControllerTest {
@Mock
private IPersonService personService;
@InjectMocks
private PersonController underTest;
@BeforeEach
void setUp() {
underTest = new PersonController(personService);
}
...Tests...
}
而相关的PersonController代码是:
public class PersonController {
@Autowired
private ModelMapper _modelMapper;
private final IPersonService _personService;
public PersonController (IPersonService personService) {
_personService = personService;
}
...Code that calls _modelMapper...
}
首先你应该用
注释你的class PersonControllerTest@ExtendWith(SpringExtension.class)
class PersonControllerTest {
或
@ExtendWith(MockitoExtension.class)
class PersonControllerTest {
取决于您的用例。这应该已经解决了您的问题。如果你还在使用 Junit4,你应该使用
@RunWith(Springrunner.class)
class PersonControllerTest {
但是因为你正在使用
@BeforeEach
不应该这样:)
编辑:
当你通过 @Autowired 使用 ModelMapper 时,你必须使用 @ExtendWith(SpringExtension.class) 。您还必须使用 @SpringBootTest 注释您的 class 或使用 @Import 注释手动导入应该通过依赖注入可用的 classes。
这里的一个问题是您正在使用 new PersonController(personService)
手动创建控制器 class,因此 spring 注释 @Autowired
在这里没有任何效果(因为 spring 不是在创建 class 不是在配置它)。
另一个问题是您使用的 mockito @InjectMocks
基本上是注入模拟(用于单元测试),但与此同时,您使用的 @SpringBootTest
用于集成测试(应用程序是正常启动,但处于测试模式)。
根据您的描述,我不清楚您是要编写单元测试还是集成测试。所以:
- 如果您正在编写单元测试代码,请删除
@SpringBootTest
添加ModelMapper
作为构造函数参数并使用两个模拟实例化 class。 - 如果您正在编写 spring integration test,请删除
@InjectMocks
和 class 的手动 class 实例化,并在测试中将控制器标记为@Autowire
。