![](/img/trans.png)
[英]Injecting Mockito Mock objects using Spring JavaConfig and @Autowired
[英]How to prevent Spring from injecting @Autowired references inside a mock?
我想使用Spring + JUnit + Mockito测试一个类,但是我无法使其正常工作。
假设我的班级引用了Service:
@Controller
public class MyController
{
@Autowired
private MyService service;
@PostConstruct
public void init() {
service.whatever();
}
public void doSomething() {
service.create();
}
}
并且此服务引用存储库:
@Service
public class MyService {
@Autowired
private MyRepository repository;
public void whatever() {}
public void create() {
repository.save();
}
}
在测试MyController类时,我希望模拟服务。 问题是: 即使服务被模拟,Spring也会尝试将存储库注入模拟中 。
这是我所做的。 测试类别:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { MyControllerTestConfiguration.class })
public class MyControllerTest {
@Autowired
private MyController myController;
@Test
public void testDoSomething() {
myController.doSomething();
}
}
配置类:
@Configuration
public class MyControllerTestConfiguration {
@Bean
public MyController myController() {
return new MyController();
}
@Bean
public MyService myService() {
return Mockito.mock(MyService.class);
}
}
我得到的错误是: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [test.test.MyRepository] found for dependency
我尝试使用Mockito的@InjectMocks
批注来初始化模拟,但这失败了,因为在模拟注入之前调用@PostConstruct
方法,生成了NullPointerException
。
而且我不能简单地模拟存储库,因为在现实生活中,这会使我模拟很多类...
谁可以帮我这个事?
使用构造函数而不是字段注入。 这使测试变得容易得多。
@Service
public class MyService {
private final MyRepository repository;
@Autowired
public MyService(MyRepository repository) {
this.repository = repository;
}
public void whatever() {}
public void create() {
repository.save();
}
}
-
@Controller
public class MyController {
private final MyService service;
@Autowired
public MyController(MyService service) {
this.service = service;
}
@PostConstruct
public void init() {
service.whatever();
}
public void doSomething() {
service.create();
}
}
这有几个优点:
NullPointerException
。 [依赖项的实例字段]可以是最终值,因此1)不能意外修改它们,以及2)任何读取该字段的线程都将读取相同的值。
丢弃@Configuration
类并编写如下测试:
@RunWith(MockitoJUnitRunner.class)
public class MyControllerTest {
@Mock
private MyRepository repository;
@InjectMocks
private MyService service;
@Test
public void testDoSomething() {
MyController myController = new MyController(service);
myController.doSomething();
}
}
使用接口,尤其是在使用某种AOP(事务,安全性等)的情况下,例如,您将拥有接口MyService
和类MyServiceImpl
。
在配置中,您将具有:
@Bean
public MyService myService() {
return Mockito.mock(MyService.class);
}
您应该将@InjectMocks批注放入控制器中,并将@Mock放入服务中,如下所示:
@Autowired
@InjectMocks
private MyController myController;
@Autowired
@Mock
private MyService myService;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
@Test
public void testDoSomething() {
myController.doSomething();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.