我试图对一个弹簧启动应用程序进行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存储库,我该如何避免这种行为?
非常感谢任何帮助!