I would like to know if it is possible to mock only the double autowired class.

Asked 2 years ago, Updated 2 years ago, 406 views

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

java spring-boot junit

2022-09-30 21:59

1 Answers

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:


2022-09-30 21:59

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.