如何模拟 Spring Data 和单元测试服务

San*_*jay 5 spring spring-data spring-boot

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

服务等级:

@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
    }
}
Run Code Online (Sandbox Code Playgroud)

测试类:

@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
    }
}
Run Code Online (Sandbox Code Playgroud)

koe*_*koe 5

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

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

@MockBean("personRepository")
private PersonRepository personRepository;
Run Code Online (Sandbox Code Playgroud)

这是完整的测试:

@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
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 0

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

但不确定您是否需要 spring 来对服务方法进行单元测试。一种更简单的方法是仅使用 Mockito 及其 @InjectMocks 注释。