Получение nullPointer в модульном тестировании службы весенней загрузки - PullRequest
0 голосов
/ 18 октября 2018

Предположим, я хочу написать юнит-тесты для этого метода

@Service
public class OfferServiceImpl implements OfferService {

@Autowired
OfferRepository OfferRepository;

@Override
public List<Offer> getAllOffers() {
    return OfferRepository.findAll();
}

Я попытался написать двумя способами.

сначала это

@RunWith(MockitoJUnitRunner.class)
public class OfferServiceTest {

@Mock
private OfferRepository offerRepositoryMock;

@InjectMocks
private OfferServiceImpl offerServiceImpl;




    @Test
        public void getAllOffersTest() {
            List<Offer> offerList=new ArrayList<>();
            offerList.add(new Offer("SE",new Date(), 10));
 //line number 47 -->>when(offerRepositoryMock.findAll()).thenReturn(offerList);
            assertNotNull(offerServiceImpl.getAllOffers());
            assertEquals(offerList, offerServiceImpl.getAllOffers());
        }

, а второе -

@RunWith(SpringRunner.class)
@SpringBootTest(classes = OfferServiceImpl.class) 
public class OfferServiceTest {

private OfferRepository offerRepositoryMock;
private OfferServiceImpl offerServiceImpl;


@Before
public void setUp() {
    offerRepositoryMock = Mockito.mock(OfferRepository.class);
    offerServiceImpl = new OfferServiceImpl();
}


@Test
public void getAllOffersTest() {
    List<Offer> offerList=new ArrayList<>();
    offerList.add(new Offer("SE",new Date(), 10));
    when(offerRepositoryMock.findAll()).thenReturn(offerList);
    assertNotNull(offerServiceImpl.getAllOffers());
    assertEquals(offerList, offerServiceImpl.getAllOffers());
}

Ниже исключения я получаю обоими способами, пытался также добавить setUp, но получаю одно и то же исключение

   FAILED: getAllOffersTest
java.lang.NullPointerException
    at com.singh.recruitsystem.service.OfferServiceTest.getAllOffersTest(OfferServiceTest.java:47)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:84)
    at org.testng.internal.Invoker.invokeMethod(Invoker.java:714)
    at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901)
    at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231)
    at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
    at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
    at org.testng.TestRunner.privateRun(TestRunner.java:767)
    at org.testng.TestRunner.run(TestRunner.java:617)
    at org.testng.SuiteRunner.runTest(SuiteRunner.java:334)
    at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:329)
    at org.testng.SuiteRunner.privateRun(SuiteRunner.java:291)
    at org.testng.SuiteRunner.run(SuiteRunner.java:240)
    at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
    at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
    at org.testng.TestNG.runSuitesSequentially(TestNG.java:1224)
    at org.testng.TestNG.runSuitesLocally(TestNG.java:1149)
    at org.testng.TestNG.run(TestNG.java:1057)
    at org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:114)
    at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:251)
    at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:77)

в чем разница между двумя вариантами и как разрешить перехват nullPOinter.Я хочу проверить это как самостоятельный.каким должен быть мой правильный способ написания модульных тестов для этого.

Ответы [ 5 ]

0 голосов
/ 18 октября 2018

Исходя из того, где вы получаете исключение NullPointerException, это - объект offerRepositoryMock, который не внедряется. Можете ли вы убедиться в импорте, что импортируется правильный import org.mockito.Mock;.

Этот примерработает для меня:

@RunWith(MockitoJUnitRunner.class)
public class Test {

    @Mock
    private Repository repositoryMock;

    @InjectMocks
    private Service service;

    @org.junit.Test
    public void getAll() {
        List list = new ArrayList();
        list.add("one");

        Mockito.when(repositoryMock.findAll()).thenReturn(list);
        List all = service.getAll();

        Assert.assertNotNull(all);
    }

    public static class Repository {
        public List findAll() {
            return new ArrayList();
        }
    }

    public static class Service {
        private Repository repository;

        public List getAll() {
            return repository.findAll();
        }
    }
}

Разница между этими двумя способами заключается в том, что если вы хотите выполнить модульное тестирование только одного класса, следует использовать первый тест MockitoJUnitRunner, а также, если вы хотите проверить взаимодействие между несколькимиклассы для проверки единицы работы, следует использовать второй тест SpringRunner, так как Spring создаст объекты и автоматически соединит их для вас.Это не обязательно будут поддельные объекты, а скорее реальные объекты.Однако вы можете переопределить реальные объекты фиктивными, предоставив @Configuration только для теста и предоставив имитированные версии объектов в этой конфигурации.

0 голосов
/ 18 октября 2018

@ Макет создает макет.@InjectMocks создает экземпляр класса и внедряет макеты, созданные с помощью аннотаций @Mock (или @Spy), в этот экземпляр.

Ваш тестовый пример терпит неудачу

@Before
 public void setUp() {
 offerRepositoryMock = Mockito.mock(OfferRepository.class);
 offerServiceImpl = new OfferServiceImpl();
 }


 @Test
 public void getAllOffersTest() {
List<Offer> offerList=new ArrayList<>();
offerList.add(new Offer("SE",new Date(), 10));
when(offerRepositoryMock.findAll()).thenReturn(offerList);
assertNotNull(offerServiceImpl.getAllOffers());
assertEquals(offerList, offerServiceImpl.getAllOffers());
}

Причина в том, что offerServiceImpl = new OfferServiceImpl ();

вы создаете макеты, но не внедряете их в сервис, поэтому ваша служба не имеет никакого представления о внедрении макетов.

Если вам нужно простое решение, просто используйте конструктор в вашем сервисе как

 @Autowired
 OfferServiceImpl(OfferRepository offerRepo) {
    this.OfferRepository = offerRepo;
 }

и в тестовом примере измените его на ниже. Это решит проблему.

 @Before
 public void setUp() {
 offerRepositoryMock = Mockito.mock(OfferRepository.class);
 offerServiceImpl = new OfferServiceImpl(offerRepositoryMock );
   }
0 голосов
/ 18 октября 2018

Во-вторых, у вас есть нулевой указатель, потому что offerRepositoryMock никогда не внедряется в ваш сервис.Вы никогда не говорите Spring для создания вашего сервиса.

A, чтобы сделать это, это добавить в свой второй тест @Autowired к вашему OfferServiceImpl и использовать аннотацию @MockBean (org.springframework.boot.test.mock.mockito.MockBean) к вашему предложениюRepositoryMock.

С этим изменением вы можете удалить свой метод установки

Надеюсь, это поможет

0 голосов
/ 18 октября 2018

Почему ты насмехался OfferServiceImpl.OfferServiceImpl - это класс, содержащий метод для тестирования.Пожалуйста, не издевайтесь над этим классом.Дразнить только класс OfferRepository и его метод findAll().Если вы это сделаете, то все остальное должно работать как есть.Фрагмент кода, приведенный ниже.

public class OfferServiceTest {

@Mock
private OfferRepository offerRepositoryMock;

private OfferServiceImpl offerServiceImpl = new OfferServiceImpl();
//Or use autowired maybe, I am not veru much familiar with Spring

@Test
public void getAllOffersTest() {
List<Offer> offerList=new ArrayList<>();
offerList.add(new Offer("SE",new Date(), 10));
when(offerRepositoryMock.findAll()).thenReturn(offerList);
assertNotNull(offerServiceImpl.getAllOffers());
assertEquals(offerList, offerServiceImpl.getAllOffers());
}
0 голосов
/ 18 октября 2018

У вас нет getter и setter для объекта offerRepository внутри класса OfferServiceImpl, поэтому даже @InjectMock не может установить его, в результате чего указатель равен нулю, я использовал отражение, чтобы сделать то же самое.

   @RunWith(SpringRunner.class)
    @SpringBootTest(classes = OfferServiceImpl.class) 
    public class OfferServiceTest {

    private OfferRepository offerRepository;
    private OfferServiceImpl offerServiceImpl;


    @Test
    public void getAllOffersTest() {
    try {
                Class<?> clazz = Class.forName("com.package.OfferRepository"); //full qualified package name
                Constructor<?> constructor = clazz.getConstructor(); //assuming default or no org constructor for OfferRepository class
                offerRepository = (OfferRepository)constructor.newInstance();
                Field decField = OfferServiceImpl.class.getDeclaredField("OfferRepository");
                decField.setAccessible(true);
                decField.set(OfferServiceImpl, offRepo);
                List<Offer> offerList=new ArrayList<>();
                    offerList.add(new Offer("SE",new Date(), 10));
                    when(offerRepository.findAll()).thenReturn(offerList);
                    assertNotNull(offerServiceImpl.getAllOffers());
                    assertEquals(offerList, offerServiceImpl.getAllOffers());

            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (SecurityException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }

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