Нулевой указатель на бобе с автопроводкой, который не издевается над мокито - PullRequest
0 голосов
/ 21 сентября 2018

У меня есть класс обслуживания, который мне нужен для модульного тестирования.У сервиса есть метод загрузки, который в свою очередь вызывает другие сервисы (бины с автопроводкой), которые обновляют базу данных.Мне нужно смоделировать некоторые из этих служб, а некоторые выполнить как есть.

@Service
public class UploadServiceImpl implements UploadService{
  @Autowired
  private ServiceA serviceA;

  @Autowired
  private ServiceB serviceB;

  public void upload(){
    serviceA.execute();
    serviceB.execute():

    //code...
}

В приведенном выше примере мне нужно смоделировать ServiceA, но я бы хотел, чтобы ServiceB работал как есть и выполнял свою функцию.Мой тест Junit выглядит следующим образом:

@RunWith(SpringJUnit4ClassRunner.class) 
@SpringBootTest(classes=Swagger2SpringBoot.class) 
public class UploadServiceTest {
  @Mock
  private ServiceA serviceA;

  @InjectMocks
  private UploadServiceImpl uploadService;

  @Before
  public void init() {
    MockitoAnnotations.initMocks(this);
  }

  @Test
  public void testUpload(){
    uploadService.upload();

  }

Когда я выполняю это, я получаю NPE на serviceB.execute(); в UploadServiceImpl.

В чем может быть проблема?

Примечание: Я не уточняю поведение смоделированного объекта, потому что мне все равно, а также поведение смоделированных объектов по умолчанию ничего не делать.

Спасибо!

Ответы [ 3 ]

0 голосов
/ 25 сентября 2018

Обычно при модульном тестировании вы хотите смоделировать все внешние зависимости класса.Таким образом, модульное тестирование может оставаться независимым и ориентироваться на тестируемый класс.

Тем не менее, если вы хотите смешать Spring-электропроводку с макетами Mockito, простое решение состоит в том, чтобы аннотировать как @InjectMocks, так и @Autowired.:

  @InjectMocks
  @Autowired
  private UploadServiceImpl uploadService;

Общий эффект этого заключается в том, что сначала Spring автоматически связывает бин, а затем Mockito немедленно перезаписывает имитированные зависимости доступными имитами.

0 голосов
/ 17 мая 2019

Проблема, с которой вы сталкиваетесь, связана с использованием аннотации @InjectMocks. @InjectMocks отмечает поле, в которое необходимо выполнить инъекцию.В этом порядке Mockito попытается внедрить макеты только с помощью инжектора конструктора, метода инсталляции или свойства.Если какая-либо из указанных стратегий внедрения не удалась, Mockito не будет сообщать о сбое.

Таким образом, в вашем случае, когда вы пытаетесь внедрить ложные сообщения, присутствует только один пробный компонент, а другой - ServiceA -не вводится. Для решения этой проблемы:

Вы можете попробовать вообще не использовать @InjectMocks, а вместо этого передавать фиктивный объект для метода, который вы хотите смоделировать, в то время как передайте остальные объекты с автопроводкой в ​​конструктор. Пример:

Здесь, чтобы проверить, я передаю один фиктивный объект и один объект с автопроводкой.

@RunWith(MockitoJUnitRunner.class)
public class SampleTestServiceImplTest {

@Mock
private SampleClient sampleClient;
@Autowired
private BackendService backendService ;

private BackendServiceImpl backendServiceimpl;

@Before
void setUp() {
    backendServiceimpl = new BackendServiceImpl(sampleClient, backendService);
}

Или другой способ сделать эту работу - использовать аннотацию @Autowired вместе с @InjectMocks.@Autowired @InjectMocks используются вместе, и то, что он будет делать, это внедрить макетированный класс, а аннотация Autowired добавляет любую другую зависимость, которую может иметь класс.

Ответ ссылается на: https://medium.com/@vatsalsinghal/autowired-and-injectmocks-in-tandem-a424517fdd29

0 голосов
/ 22 сентября 2018

Добавьте

  @Mock
  private ServiceB serviceB;

, чтобы создать инъекционный макет отсутствующего сервиса, как вы это сделали с сервисом A.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...