【问题标题】:How to mock Spring Data and unit test service如何模拟 Spring Data 和单元测试服务
【发布时间】:2016-07-10 16:28:47
【问题描述】:

我正在尝试对服务方法进行单元测试。服务方法调用 spring 数据存储库方法来获取一些数据。我想模拟该存储库调用,并自己提供数据。怎么做?在Spring Boot documentation 之后,当我模拟存储库并直接在我的测试代码中调用存储库方法时,模拟正在工作。但是当我调用服务方法时,它又会调用存储库方法,模拟不起作用。下面是示例代码:

服务类:

@Service
public class PersonService {

    private final PersonRepository personRepository;

    @Autowired
    public PersonService(personRepository personRepository) {

        this.personRepository = personRepository;
    }

    public List<Person> findByName(String name) {
        return personRepository.findByName(name); // I'd like to mock this call
    }
}

测试类:

@RunWith(SpringRunner.class)
@SpringBootTest
public class ApplicationTests {

    // http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-testing-spring-boot-applications-mocking-beans
    @MockBean
    private PersonRepository personRepository;

    @Autowired
    private PersonService personService;

    private List<Person> people = new ArrayList<>();

    @Test
    public void contextLoads() throws Exception {

        people.add(new Person());
        people.add(new Person());

        given(this.personRepository.findByName("Sanjay Patel")).willReturn(people);

        assertTrue(personService.findByName("Sanjay Patel") == 2); // fails
    }
}

【问题讨论】:

  • 请显示一些代码。您是否在服务中设置了模拟存储库?如果没有,那是必要的。
  • 哦!我需要在服务中手动注入存储库,对吗?谢谢@dunni
  • 这取决于你的测试是什么样子的。正如我所说,发布一些代码。
  • @Dunni,我已经发布了一些代码。那么,我将不得不使用 setter 注入而不是构造函数注入,并手动注入 mocked 存储库?
  • 你的测试目的无效,因为如果你的持久层被破坏,模拟测试仍然会成功

标签: spring spring-boot spring-data


【解决方案1】:

对于 Spring Data 存储库,您需要指定 bean 名称。通过类型模拟似乎不起作用,因为存储库是运行时的动态代理。

PersonRepository 的默认 bean 名称是“personRepository”,所以应该可以:

@MockBean("personRepository")
private PersonRepository personRepository;

这是完整的测试:

@RunWith(SpringRunner.class)
@SpringBootTest
public class ApplicationTests {

    // http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-testing-spring-boot-applications-mocking-beans
    @MockBean("personRepository")
    private PersonRepository personRepository;

    @Autowired
    private PersonService personService;

    private List<Person> people = new ArrayList<>();

    @Test
    public void contextLoads() throws Exception {

        people.add(new Person());
        people.add(new Person());

        given(this.personRepository.findByName("Sanjay Patel")).willReturn(people);

        assertTrue(personService.findByName("Sanjay Patel") == 2); // fails
    }
}

【讨论】:

    【解决方案2】:

    可能存储库用@MockedBean 注解标记。如果存储库是模拟的,我不知道 Spring 是否可以按类型自动连接。 您可以定义 @Bean 方法并返回 Mockito.mock(X.class),这应该可以工作。

    不确定是否需要 spring 来对服务方法进行单元测试。一种更轻松的方法是仅使用带有 @InjectMocks 注释的 Mockito。

    【讨论】:

      猜你喜欢
      • 2013-03-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多