英文:
Spring Boot / JUnit 5 / Mockito - mocking dependencies in Test classes
问题
我尝试编写JUnit 5测试用例来测试Spring Boot API,但在测试类中遇到了依赖注入的问题。我希望测试ProfileController中的端点,该Controller有3个依赖项:ProfileService、ProfileModelAssembler(用于向JSON响应添加REST相关装饰,例如“链接”)和ModelMapper。在我的测试类中,我使用以下方式对它们进行了注释:
@InjectMocks
ProfileController profileController;
@Mock
ProfileService profileService;
@Mock
ProfileModelAssembler profileModelAssembler;
@Mock
ModelMapper modelMapper;
当我尝试运行测试时,由于ProfileService的依赖项未满足,它会报错("No qualifying bean of type x.ProfileService available")。
在我的ProfileController中,我尝试直接使用@Autowired注解这些字段(我知道这不是推荐的做法):
@Autowired
private ProfileService profileService;
@Autowired
private ProfileModelAssembler profileModelAssembler;
@Autowired
private ModelMapper modelMapper;
以及通过构造函数注入的方式:
@Autowired
public ProfileController(ProfileService profileService, ProfileModelAssembler profileModelAssembler, ModelMapper modelMapper) {
this.profileService = profileService;
this.profileModelAssembler = profileModelAssembler;
this.modelMapper = modelMapper;
}
但无论哪种方式,错误都是一样的。我发现关于JUnit和Mockito的教程方法多种多样,各不相同,这让我感到困惑。我知道解决问题通常有多种方法,但我很惊讶于没有什么“首选”做法。是否有建议可以消除此错误,或者有哪些资源可以帮助我以“简单”的方式满足我的相对简单需求来学习JUnit/Mockito?
英文:
I am trying to write JUnit 5 tests for a Spring Boot API but running into problem with dependency injection in the Test class. I wish to test endpoints in the ProfileController, which has 3 dependencies: ProfileService, ProfileModelAssembler (to add REST-centric decorations to json response, e.g. "links") and ModelMapper. In my Test class, I have the following 3 annotated as shown:
@InjectMocks
ProfileController profileController;
@Mock
ProfileService profileService;
@Mock
ProfileModelAssembler profileModelAssembler;
@Mock
ModelMapper modelMapper;
When I try to run a test, it errors out instantiating the ProfileController due to unsatisfied dependency for the ProfileService ("No qualifying bean of type x.ProfileService available").
In my ProfileController, I have tried to @Autowire those fields directly (not recommended, I know):
@Autowired
private ProfileService profileService;
@Autowired
private ProfileModelAssembler profileModelAssembler;
@Autowired
private ModelMapper modelMapper;
as well as via constructor injection:
@Autowired
public ProfileController(ProfileService profileService, ProfileModelAssembler profileModelAssembler, ModelMapper modelMapper) {
this.profileService = profileService;
this.profileModelAssembler = profileModelAssembler;
this.modelMapper = modelMapper;
}
Error is the same either way. Tutorials I have found for JUnit and Mockito are absolutely all over the place in approach, doing things radically different from one another. I know there are always multiple solutions to a problem, but I've been surprised at how little adherence to any sort of "preferred" practice there is. Any recommendations to eliminate this error or resources to which I could turn to learn JUnit/Mockito in a "simple" way for my relatively simple needs?
答案1
得分: 3
@Mock
和@InjectMocks
注解与Spring无关,因此在ProfileController
类中如何自动装配依赖项并不重要。从您收到的错误看,似乎您正在使用@SpringBootTest
运行测试,这会启动应用程序上下文,因此您需要在ProfileService
等上使用@MockBean
注解,以便它们被注入到应用程序上下文中。
或者,您可以在不启动整个应用程序上下文的情况下进行基本单元测试,在这种情况下,@Mock
和@InjectMocks
注解将按您期望的方式工作。只需确保正确初始化模拟对象。最简单的方法是在测试类上注释@ExtendWith(MockitoExtension.class)
。
英文:
@Mock
and @InjectMocks
annotations have nothing to do with Spring so it doesn't matter how you autowire the dependencies in the ProfileController
class. From the error you got it looks like you are running the test with @SpringBootTest
where the application context is started so you would need to use the @MockBean
annotations on ProfileService
and others in order for them to be injected into the application context.
Alternatively, you can have a basic unit test without starting the whole application context where @Mock
and @InjectMocks
annotations would work as you expect. Just make sure to properly initialize the mocks. The easiest way would be to annotate the test class with @ExtendWith(MockitoExtension.class)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论