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.
** 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.
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.
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();
}
}
@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();
}
}