JunitTest генерирует InvocationTargetException при использовании теста Spring MVC - PullRequest
0 голосов
/ 29 января 2019

Я использую JUnitTest и Mock test Spring MVC test getAll Employee, но он выдает ошибку «InvocationTargetException» при запуске в строке: when (customerService.findAllCustomer ()). ThenReturn (Arrays.asList (customer, customer1)); .Не знаю почему?Ниже мой тест.

CustomerControllerTest.

import com.baotrung.config.PersistenceJPAConfig;
import com.baotrung.config.WebConfig;
import com.baotrung.domain.Customer;
import com.baotrung.service.CustomerService;
import org.hamcrest.collection.IsCollectionWithSize;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static org.hamcrest.Matchers.*;
import static org.mockito.Mockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {PersistenceJPAConfig.class, WebConfig.class})
@WebAppConfiguration
public class CustomerControllerTest {

    private MockMvc mockMvc;
    private List<Customer> customers = new ArrayList<>();

    @Mock
    private CustomerService customerService;

    @Test
    public void findAll() throws Exception {
        Customer customer = new Customer();
        customer.setId(1L);
        customer.setFirstName("Nguyen Van");
        customer.setLastName("A");
        customer.setEmail("nguyenvana@gmail.com");

        Customer customer1 = new Customer();
        customer1.setId(2L);
        customer1.setFirstName("Nguyen Van");
        customer1.setLastName("A");
        customer1.setEmail("nguyenvana@gmail.com");
        customers.add(customer);
        customers.add(customer1);
        when(customerService.findAllCustomer()).thenReturn(Arrays.asList(customer,customer1));
        mockMvc.perform(get("/"))
                .andExpect(status().isOk())
                .andExpect(view().name("customers/findAll"))
                .andExpect(forwardedUrl("/WEB-INF/views/list.jsp"))
                .andExpect(model().attribute("customers", IsCollectionWithSize.hasSize(2)))
                .andExpect(model().attribute("customers", hasItem(
                        allOf(
                                hasProperty("id", is(1L)),
                                hasProperty("firstName", is("Nguyen Van")),
                                hasProperty("lastName", is("A"))
                        )
                )))
                .andExpect(model().attribute("customers", hasItem(
                        allOf(
                                hasProperty("id", is(1L)),
                                hasProperty("firstName", is("Nguyen Van")),
                                hasProperty("lastName", is("A"))
                        )
                )));
        verify(customerService, times(1)).findAllCustomer();
        verifyNoMoreInteractions(customerService);
    }
}

Контроллер.

@Controller
@RequestMapping("customers")
public class CustomerController {

    @Autowired
    private CustomerServiceImpl customerService;

    @GetMapping("/findAll")
    public String findAllCustomer(Model model) {
        List<Customer> customers = customerService.findAllCustomer();
        if (customers.isEmpty()) {
            throw new ResourceNotFoundException("Can't find anything customer");
        }

        model.addAttribute("customers", customers);
        return "list";
    }


}

Клиент.

package com.baotrung.domain;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import java.util.Objects;

@Entity
public class Customer {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String firstName;

    private String lastName;

    private String email;

    public Customer() {
    }

    public Customer(String firstName, String lastName, String email) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.email = email;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @Override
    public boolean equals(Object obj) {
        return super.equals(obj);
    }

    @Override
    public int hashCode() {

        return Objects.hash(id, firstName, lastName, email);
    }

    @Override
    public String toString() {
        return "Customer{" +
                "id=" + id +
                ", firstName='" + firstName + '\'' +
                ", lastName='" + lastName + '\'' +
                ", email='" + email + '\'' +
                '}';
    }
}

CustomerRepository.

public interface CustomerRepository extends CrudRepository<Customer, Long> {
}

Модель.

 package com.baotrung.domain;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import java.util.Objects;

@Entity
public class Customer {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String firstName;

    private String lastName;

    private String email;

    public Customer() {
    }

    public Customer(String firstName, String lastName, String email) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.email = email;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @Override
    public boolean equals(Object obj) {
        return super.equals(obj);
    }

    @Override
    public int hashCode() {

        return Objects.hash(id, firstName, lastName, email);
    }

    @Override
    public String toString() {
        return "Customer{" +
                "id=" + id +
                ", firstName='" + firstName + '\'' +
                ", lastName='" + lastName + '\'' +
                ", email='" + email + '\'' +
                '}';
    }
}

Сервис.

package com.baotrung.service;

import com.baotrung.domain.Customer;
import com.baotrung.exception.ResourceNotFoundException;
import com.baotrung.repository.CustomerRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

    @Service
    public class CustomerServiceImpl implements CustomerService {
        @Autowired
        private CustomerRepository customerRepository;

        @Override
        @Transactional(readOnly = true)
        public List<Customer> findAllCustomer() {
            return (List<Customer>) customerRepository.findAll();
        }

        @Override
        @Transactional
        public void saveCustomer(Customer customer) {
            customerRepository.save(customer);
        }

        @Override
        @Transactional(readOnly = true)
        public Customer getCustomer(Long id) {
            return customerRepository.findById(id).orElseThrow(() -> new ResourceNotFoundException("Can't find any customer with id:" + id));
        }

        @Override
        @Transactional
        public void deleteCustomer(Long id) {
            customerRepository.deleteById(id);
        }
    }

При запуске выдается исключение в строке: when (customerService.findAllCustomer ()). thenReturn (Arrays.asList (customer, customer1)); Ошибка:

org.mockito.exceptions.misusing.MissingMethodInvocationException: 
when() requires an argument which has to be 'a method call on a mock'.
For example:
    when(mock.getArticles()).thenReturn(articles);

Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
   Those methods *cannot* be stubbed/verified.
2. inside when() you don't call method on mock but on some other object.
3. the parent of the mocked class is not public.
   It is a limitation of the mock engine.


    at com.baotrung.controller.CustomerControllerTest.findAll(CustomerControllerTest.java:54)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

Обновление:

Когда я удаляю аннотацию @Autowired и добавляю аннотацию @Mockэто выдает мне ошибку:

java.lang.NullPointerException
    at com.baotrung.controller.CustomerControllerTest.findAll(CustomerControllerTest.java:55)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

1 Ответ

0 голосов
/ 29 января 2019

Я подозреваю, что проблема связана с использованием CustomerService в тестовом коде.Это настоящий боб, а не насмешливый.Вам нужно смоделировать это, чтобы настроить ожидания.

@Autowired
private CustomerService customerService;

Я полагаю, @MockBean (если используется подпружиненная загрузка), в противном случае вам нужно определить поддельную версию CustomerService, которая решит вашу задачу, но дастэто попытка.

Как вы можете это сделать? Вы можете определить новый макетированный экземпляр CustomerService в классе SpringConfiguration и использовать его в своем тестовом классе, @ContextConfiguration позволяет упомянутьлюбой класс конфигурации, который вы хотите использовать.Кроме того, вам необходимо перейти от внедрения свойства к внедрению на основе конструктора для поддерживаемого кода в вашем CustomerServiceImpl.

@Service
public class CustomerServiceImpl implements CustomerService {
    @Autowired
    private CustomerRepository customerRepository;
    ...
}

, например:

@Service
public class CustomerServiceImpl implements CustomerService {
    private CustomerRepository customerRepository;

    @Autowired
    public CustomerServiceImpl(CustomerRepository customerRepository) {
        this.customerRepository = customerRepository;
    }

    ...
}

Шаги для решения:

  1. CustomerController не должен использовать CustomerServiceImpl в качестве внедренного компонента, скорее это должен быть CustomerService.
  2. Изменить определение CustomerServiceImpl, как предложено выше.
  3. Определить TestConfiguration.java, вкоторый вы определяете макетированный экземпляр CustomerService.открытый класс TestConfiguration {@Bean public CustomerService customerService () {return Mockito.mock (CustomerService.class);}}
  4. Обновите тестовый класс @ContextConfiguration до @ContextConfiguration(classes = {TestConfiguration.class, PersistenceJPAConfig.class, WebConfig.class})

Сделайте это и проверьте.

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