Questions about SpringBoot dependency injection and unit testing.
Based on the class being tested, is it possible to test only the classes that are double autowired by Mock?
Specifically, I would like to do the following tests.
·The test target is MainServiceImpl
·SubMainServiceImpl is not mocked, but uses the processing as it is
·Mock SubSubMainServiceImpl and change the output string of subSayHello()
Some people may say, "Separate the test class in the first place and mock only the classes that depend on you directly." I would like to know if the above is technically possible.
// Class you want to run directly in the test
@Service
public class MainServiceImplementationsMainService{
@Autowired
private SubMainService subMainService;
@ Override
public String mainSayHello() {
return "MainSayHello.Also..." + subMainService.subSayHello();
}
}
// The class on which MainServiceImpl depends
@Service
public classSubMainServiceImplementationsSubMainService{
@Autowired
private SubSubMainService subSubMainService;
@ Override
public String subSayHello() {
return "SubSayHello.Also..." + subSubSubMainService.subSayHello();
}
}
// The class on which SubMainServiceImpl depends
@Service
public classSubSubSubMainServiceImplementationsSubSubMainService{
@ Override
public String subSubSayHello() {
return "SubSubSubSayHello";
}
}
Incidentally, I have already learned how to use @InjectMocks and @Mocks to turn directly dependent classes into Mocks.
// Test to Mock directly dependent classes
@RunWith (SpringJUnit4ClassRunner.class)
@ SpringBootTest (webEnvironment=SpringBootTest.WebEnvironment.RANDOM_PORT)
public class MockMainServiceTest{
@InjectMocks
MainServiceImpl mainService;
@Mock
SubMainService subMainService;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
@ Test
Mock public void subclass(){
doReturn("SubMainService is Mocked").when(subMainService).subSayHello();
Assert.assertThat(mainService.mainSayHello(), is("MainSayHello.Also...SubMainService is Mocked"));
}
}
Specification Technology
SpringBoot 2.5.4
JUnit 4.2
Java 1.8
The test code in the questionnaire does not use a container (if you really want to do such a test, you do not need to give @SpringBootTest
, @RunWith
(the result will not change without it).
To test a container-managed object, code similar to the following:
Inject @Autowired
to test, and use @MockBean
for mock Spring Bean generation.
@RunWith (SpringJUnit4ClassRunner.class)
@ SpringBootTest (webEnvironment=SpringBootTest.WebEnvironment.RANDOM_PORT)
public class MockMainServiceTest{
@Autowired
MainService mainService;
@MockBean
SubMainService subMainService;
@ Test
Mock public void subclass(){
doReturn("SubMainService is Mocked").when(subMainService).subSayHello();
Assert.assertThat(mainService.mainSayHello(), is("MainSayHello.Also...SubMainService is Mocked"));
}
}
If the test you want to do is like the code above, you can write it in the same way if you want to mock only SubSubSubMainService
.
@RunWith (SpringJUnit4ClassRunner.class)
@ SpringBootTest (webEnvironment=SpringBootTest.WebEnvironment.RANDOM_PORT)
public class MockMainServiceTest{
@Autowired
MainService mainService;
@MockBean
SubSubMainService subSubMainService;
@ Test
Mock public void subclass(){
doReturn("SubSubSubMainService is Mocked").when(subSubSubMainService).subSubSubSayHello();
Assert.assertThat(mainService.mainSayHello(),
is("MainSayHello.Also...SubSayHello.Also...SubSubSubMainService is Mocked"));
}
}
Note:
© 2024 OneMinuteCode. All rights reserved.