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 用于集成测试(应用程序是正常启动,但处于测试模式)。

根据您的描述,我不清楚您是要编写单元测试还是集成测试。所以:

  1. 如果您正在编写单元测试代码,请删除 @SpringBootTest 添加 ModelMapper 作为构造函数参数并使用两个模拟实例化 class。
  2. 如果您正在编写 spring integration test,请删除 @InjectMocks 和 class 的手动 class 实例化,并在测试中将控制器标记为 @Autowire