弹簧靴& junit:如何在使用@ComponentScan时模拟CRUD存储库?

时间:2016-05-30 13:40:32

标签: java spring unit-testing junit

我试图对一个弹簧启动应用程序进行junit测试。对于这个问题,我创建了一个简单的例子来说明我的问题。

服务bean:

@Service
public class DummyService {
    public String dummyMethod(String str) {
        return "Dummy(" + str + ")";
    }
}

实体类:

@Entity
public class KeyValue {

    @Id
    @GeneratedValue
    Long id;

    @Column(nullable = false)
    String key;

    @Column(nullable = false)
    String value;
}

和存储库:

public interface KeyValueRepository extends CrudRepository<KeyValue, Long>
{
}

所有这些都是@Autowired到控制器。

对于单元测试,我创建了一个Configuration类:

@Configuration
public class MyTestConfig {

    @Bean
    public DummyService dummyService() {
        return new DummyService();
    }

    @Bean
    public KeyValueRepository keyValueRepository() {
        return  Mockito.mock(KeyValueRepository.class);
    }
}

如果我现在测试它,它的效果非常完美:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = MyTestConfig.class)
public class UsingMockTest {

    @Autowired
    KeyValueRepository keyValueRepository;

    @Test
    public void respositoryIsMock()
    {
        MockUtil mo = new MockUtil();
        assertTrue(mo.isMock(keyValueRepository));
    }
}

这给了我一个模拟版本的存储库,正如预期的那样。

然而,事实证明这种方法不适合更大的应用程序。我们的真实应用程序包含50多个bean,它们都是自动装配的。所以我想做的是@ComponentScan应用程序然后,在我的配置中只覆盖我实际想要模拟的bean。

但是,如果我像这样设置测试配置:

@Configuration
@ComponentScan(
        basePackages = {"com.example"}
)
public class MyTestConfig {

    @Bean
    public DummyService thisForThatService() {
        return new DummyService();
    }

    @Bean
    public KeyValueRepository sayingRepository() {
        return Mockito.mock(KeyValueRepository.class);
    }
}

我将获得失败的测试,因为存储库不再是模拟对象。当我查看spring boot日志时,我看到以下内容:

2016-05-30 15:36:50.539  INFO 5908 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Overriding bean definition for bean 'dummyService' with a different definition: 
    replacing [Generic bean: class [com.example.DummyService]; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in file [C:\work\dev\testDemo\build\classes\main\com\example\DummyService.class]]
    with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=myTestConfig; factoryMethodName=dummyService; initMethodName=null; destroyMethodName=(inferred); defined in com.example.MyTestConfig]
2016-05-30 15:36:50.658  INFO 5908 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Overriding bean definition for bean 'keyValueRepository' with a different definition:
    replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=myTestConfig; factoryMethodName=keyValueRepository; initMethodName=null; destroyMethodName=(inferred); defined in com.example.MyTestConfig]
    with [Root bean: class [org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null]

因此,对于简单的&#34; DummyBean&#34;,我在MyTestConfig类中的显式配置(这正是我想要的)覆盖扫描的配置,但对于CRUD存储库,来自的模拟bean MyTestConfig类被组件扫描的JPA bean覆盖。

为了能够注入@Autowired模拟CRUD存储库,我该如何避免这种行为?

非常感谢任何帮助!

0 个答案:

没有答案