Вам нужно использовать ArgumentMatcher при настройке макета - вместо передачи строкового литерала "abc"
, вам нужно, чтобы ваша строка выглядела как when(service01.name(eq("abc"))).thenReturn...
Если вы не возражаете против фактической строки, то есть и другие сопоставители, которые вы можете использовать, например anyString()
.
Вы также не хотите использовать @Autowired
в своем тесте - если вы хотите, чтобы тестируемый класс автоматически вставлял в него mock, вам нужно создать экземпляры mock и сделать их инъекционными, а не реальными bean-компонентами Spring.
Самый простой способ сделать это - использовать аннотации MockitoJUnitRunner
и @InjectMocks
:
@RunWith(MockitoJUnitRunner.class)
public class TestCalss {
@Mock
private Service01 service01;
@InjectMocks
private Service02 service02;
...
Чтобы внедрить класс, который не является фиктивным, вам нужно использовать аннотацию @Before
, с некоторым способом передачи объекта в класс (как в обычном Java-коде).
Мой предпочтительный способ сделать это - иметь конструктор, который устанавливает зависимости как частные конечные поля класса, но Spring также предоставляет класс ReflectionTestUtils
, который можно использовать, если вы действительно хотите придерживаться закрытых полей без сеттеры.
Так что-то вроде этого:
@Service
public class Service02 {
private final Service01 service01;
private final Service03 service03;
@Autowired
public Service02 (Service01 service01, Service03 service03) {
this.service01 = service01;
this.service03 = service03;
}
...
}
@RunWith(MockitoJUnitRunner.class)
public class TestClass {
@Mock
private Service01 service01;
private Service02 underTest;
@Before
public void setup() {
this.underTest = new Service02(this.service01, new Service03());
}
...
}
Если вы хотите вызвать реальный метод для объекта, который иначе хотите смоделировать, то это может быть признаком того, что ваш класс делает слишком много и на самом деле должен быть двумя или более меньшими классами, но это также возможно: when(someMock.someMethod()).thenCallRealMethod();