[JAVA] Spring superclass mocking

I couldn't run the test that mocked the superclass in spring, and I got stuck for a while. I needed to identify the class to mock.

Failure example

** Confirmed with Spring Boot 2.0.5 **

Prepare two classes that have an inheritance relationship. These are plunged into the DI container with @Component.

** Superclass **

@Component
public class SuperClass {

    void superClassMethod() {
        System.out.println("You called a superclass method.");
    }
}

** Subclass **

@Component
public class SubClass extends SuperClass {

    void subClassMethod() {
        System.out.println("You called a method in a subclass.");
    }
}

Write a test to mock and use a superclass with @ MockBean.

** Test code **

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class SampleTest {

    @MockBean
    SuperClass superClass;

    @Test
    public void sampleTest() {
        doNothing().when(superClass).superClassMethod();
    }
}

I will do it.

** Test execution result **

Caused by: java.lang.IllegalStateException: Unable to register mock bean com.example.vendingmachine.sample.SuperClass expected a single matching bean to replace but found [subClass, superClass]

Died safely.

What's wrong

Looking at the exception message, there is the following description.

expected a single matching bean to replace but found [subClass, superClass]

In short, "Since there are two mocking targets, subClass and superClass, I don't know which one should be mocked." If there is a subclass in the mocking target class, that is also determined to be the mocking target.

solution

Just use @Quelifer to declare" Mock the superclass! "As shown below.

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class SampleTest {

    @MockBean
    @Qualifier("superClass")
    SuperClass superClass;

    @Test
    public void sampleTest() {
        doNothing().when(superClass).superClassMethod();
    }
}

For @SpyBean

In the case of @SpyBean that can be mocked on a method-by-method basis, an error will occur with the same feeling.

** Test code **

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class SampleTest {

    @SpyBean
    SuperClass superClass;

    @Test
    public void sampleTest() {
        doNothing().when(superClass).superClassMethod();
    }
}

** Test execution result **

java.lang.IllegalStateException: No bean found for definition [SpyDefinition@f2b90fc name = '', typeToSpy = com.example.vendingmachine.sample.SuperClass, reset = AFTER]

In this case, it is OK if you put the superclass name in the name attribute of @ SpyBean as shown below.

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class SampleTest {

    @SpyBean(name = "superClass")
    SuperClass superClass;

    @Test
    public void sampleTest() {
        doNothing().when(superClass).superClassMethod();
    }
}

reference

Use Qualifier tag with Autowired of Spring Framework

Recommended Posts

Spring superclass mocking
spring × docker
About Spring ③
Spring Java