Junit Mocking бросает нулевой указатель - PullRequest
0 голосов
/ 11 ноября 2018

Я пытаюсь издеваться над классом обслуживания ниже.

Я создал отдельный компонент Config, который я вызываю, как вы можете видеть ниже в коде: -

@Component
public class CrawlerService implements CrawlerServiceInterface {

    private static final Logger LOGGER = LoggerFactory.getLogger(CrawlerService.class);

    private final CrawlConfig config;

    @Autowired
    CrawlerFactory crawlerFactory;

    @Autowired
    public CrawlerService(@Qualifier(value = "CrawlerConfig") CrawlConfig config) {
        this.config = config;
    }

    @Value("${com.prudential.noOfCrawlers}")
    private int numberOfCrawlers;

    @Override
    public Object crawlService(String URL, int max) throws Exception {

        LOGGER.info("In Service Class");

        this.config.setMaxPagesToFetch(max);

        PageFetcher pageFetcher = new PageFetcher(config);
        RobotstxtConfig robotstxtConfig = new RobotstxtConfig();
        RobotstxtServer robotstxtServer = new RobotstxtServer(robotstxtConfig, pageFetcher);
        CrawlController controller = new CrawlController(config, pageFetcher, robotstxtServer);

        controller.addSeed(URL);
        controller.start(crawlerFactory, numberOfCrawlers);

        List<Object> crawlersLocalData = controller.getCrawlersLocalData();

        LOGGER.info("End of Service Class");
        return crawlersLocalData;

    }

}

Проблема в том, что я получаю исключение нулевого указателя в this.config.setMaxPagesToFetch.

Что я делаю не так?

Если я смоделировал некоторый зависимый объект с аннотацией @Mock, значит ли это, что он не позволит изменить значение?

Вот тестовый класс: -

List<Object> obj=new ArrayList<Object>();

@Mock
private CrawlConfig config;

@Mock
CrawlerFactory crawlerFactory;

@Mock
CrawlController controller;

@InjectMocks
CrawlerService crawlerService = new CrawlerService(config);

@Before
public void setUp() throws Exception {
    MockitoAnnotations.initMocks(this);
}

@Test
public void testService() throws Exception {
    when(controller.getCrawlersLocalData()).thenReturn(obj);

    assertEquals(crawlerService.crawlService("https://vogella.com", 10), obj);

}

1 Ответ

0 голосов
/ 12 ноября 2018

Здесь у вас проблема с макетом создания заказа. Прежде всего, давайте посмотрим, что здесь происходит:

  • Во-первых, вы объявляете некоторые поля. В этом случае вы объявляете private CrawlConfig config и CrawlerService crawlerService. Но crawlerService вы не просто объявляете, но и инициализируете.
  • Когда вы инициализируете его, вы передаете в качестве зависимости CrawlConfig config, что составляет null.
  • Тогда MockitoAnnotations.initMocks(this) начните творить чудеса. Что оно делает? Он инициализирует все поля, помеченные @Mock, затем пытается инициализировать @InjectMocks, если он еще не инициализирован. В вашем случае он уже инициализирован, поэтому mockito не инициализирует его и будет использовать созданный вами экземпляр.
  • После этого имитирует инъекцию. Mockito будет пытаться использовать любую из своих стратегий для инъекций. Вы можете прочитать больше об этом в @ InjectMocks javadoc . Так что в вашем случае mockito попытается использовать установщик свойства или внедрение поля. Однако CrawlConfig config в вашем CrawlerService объявлено final, и mockito будет игнорировать это поле, так как для этого типа внедрения mockito игнорирует поля final или static.

Итак, вы создали экземпляр CrawlerService с зависимостью CrawlConfig config, равной null, и mockito ничего с этим не сделает.

1) Вы можете издеваться над CrawlConfig config до того, как mockito собирается:

private CrawlConfig config = Mockito.mock(CrawlConfig.class);

@InjectMocks
CrawlerService crawlerService = new CrawlerService(config);

2) Вы можете опустить инициализацию CrawlerService и положиться на mockito:

@Mock
private CrawlConfig config = Mockito.mock(CrawlConfig.class);

@InjectMocks
CrawlerService crawlerService;

Каждый из этих методов должен работать.

Вы также можете удалить объявление final из вашего CrawlerService, и оно также будет работать. Но, как по мне, два метода выше - лучшие варианты.

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