Spring Boot:在单元测试中覆盖多个bean

时间:2017-07-19 13:22:11

标签: java spring unit-testing spring-boot

我的项目中有一些Repository - bean。我将此回购的集合连接到我的一些服务,并迭代地从每个服务中获取数据。但是在我的单元测试中,我想从Spring上下文中排除所有这些存储库(实际实现),并且只使用伪造的。我如何实现它?

3 个答案:

答案 0 :(得分:0)

测试自动配置:

让我们创建一个非常简单的示例来测试我们的自动配置。我们将使用Spring Data创建一个名为MyUser的实体类和一个MyUserRepository接口:

@Entity
public class MyUser {
    @Id
    private String email;

    // standard constructor, getters, setters
}
public interface MyUserRepository 
  extends JpaRepository<MyUser, String> { }

要启用自动配置,我们可以使用其中一个@SpringBootApplication@EnableAutoConfiguration注释:

@SpringBootApplication
public class AutoconfigurationApplication {
    public static void main(String[] args) {
        SpringApplication.run(AutoconfigurationApplication.class, args);
    }
}

接下来,让我们编写一个保存MyUser实体的JUnit测试:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(
  classes = AutoconfigurationApplication.class)
@EnableJpaRepositories(
  basePackages = { "com.baeldung.autoconfiguration.example" })
public class AutoconfigurationTest {

    @Autowired
    private MyUserRepository userRepository;

    @Test
    public void whenSaveUser_thenOk() {
        MyUser user = new MyUser("user@email.com");
        userRepository.save(user);
    }
}

由于我们尚未定义DataSource配置,因此应用程序将使用我们创建的自动配置连接到名为myDb的MySQL数据库。

连接字符串包含createDatabaseIfNotExist=true属性,因此数据库不需要存在。但是,需要创建用户mysqluser或通过mysql.user属性指定的用户mysqluser,如果它存在,则需要创建。

我们可以检查应用程序日志以查看是否正在使用MySQL数据源:

web - 2017-04-12 00:01:33,956 [main] INFO  o.s.j.d.DriverManagerDataSource - Loaded JDBC driver: com.mysql.cj.jdbc.Driver

禁用自动配置类

如果我们想要排除自动配置,我们可以将@EnableAutoConfiguration注释添加excludeexcludeName属性到配置类:

@Configuration
@EnableAutoConfiguration(
  exclude={MySQLAutoconfiguration.class})
public class AutoconfigurationApplication {
    //...
}

禁用特定自动配置的另一个选项是设置spring.autoconfigure.exclude属性:

spring.autoconfigure.exclude=com.baeldung.autoconfiguration.MySQLAutoconfiguration

资源链接:Create a Custom Auto-Configuration with Spring Boot

溶液#2:

Matt C也在本教程中提供了解决方案:How to exclude *AutoConfiguration classes in Spring Boot JUnit tests?

答案 1 :(得分:0)

Spring单元测试中很少使用Spring上下文。第一个问题你应该问自己:“我想测试哪些工作单元?”。得到答案后,您应该在隔离中对其进行测试。你不需要弹簧上下文。通常在集成测试中需要Spring上下文。单元测试不得依赖于上下文。

您可以使用@Mock提供的@InjectMocksMockito注释。例如:

public class SomeServiceTest {

    @InjectMocks
    SomeService someService;

    @Mock
    PersonRepository personRepository;

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

    @Test
    public void testFindPersonExpectOk(){
        String name = "John";
        String secondName = "Doe";

        // Configure the behavior for mocked repository
        Person person = new Person(name, secondName);
        when(personRepository.findByNameAndSecondName(name, 
            secondName).thenReturn(person);

        // Call some method in testing service
        Person fetchedPerson = someService.findUser(name, secondName);

        // Check that everything is fine
        assertThat(fetchedPerson.getName, is(name));

    }
}

答案 2 :(得分:0)

以下是解决方案:

@SpringBootApplication
@ComponentScan(basePackages = "my.base.package",
        excludeFilters = @ComponentScan.Filter(type = FilterType.REGEX, pattern = "my.base.package.repositories.*.*"))
public class TestApplication {

    public static void main(String[] args) {
        SpringApplication.run(TestApplication.class, args);
    }

    @Bean
    public Repository someFakeRepository() {
        return new FakeRepository();
    }

}

然后是测试班:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestApplication.class)
public class ApplicationTests {

    @Autowired
    private Repository fakeRepository;

    // tests

}

所以我用测试版替换了所有真正的bean。