在服务测试中使用真实组件
Posted
技术标签:
【中文标题】在服务测试中使用真实组件【英文标题】:Use a real component in a service test 【发布时间】:2019-08-18 03:47:11 【问题描述】:我正在测试具有自动装配帮助器组件的服务。该组件具有自动装配的 repo。
在我的测试中,我想使用那个组件助手,而不是模拟。我想为此模拟 repo。
但我无法让它工作。
我测试的服务:
@Service
public class ServiceImpl
@Autowired
private Helper helper;
具有自动装配 repo 的 Helper 类
@Component
public class Helper
@Autowired
private Repository repo;
我的测试应该是这样的
@ExtendWith(MockitoExtension.class)
public class ServiceImplTest
ServiceImpl service;
@Mock
private Repository repoMock;
@InjectMocks
private Helper helper;
我想重构整个事情,但不幸的是,这是不可能的......
欢迎任何帮助。
【问题讨论】:
Repository
是类还是接口?
Repository 是一个接口
【参考方案1】:
尝试为您的测试加载配置,优先考虑模拟存储库已测试:
@RunWith(SpringRunner.class)
@SpringBootTest
public class SomeTest
@Configuration
static class ContextConfiguration
@Bean
public Helper helper()
return new Helper();
@Bean
@Primary
public Repository repoMock()
Repo repo = Mockito.mock(Repository.class);
Mockito.when(/* Mock your repo */);
return repo;
@Autowired
private Helper helper;
@Test
public void testMethod()
// Your test goes here
无论如何,请记住该字段自动装配is evil。尽快切换到构造函数依赖注入。
另请参阅:
https://***.com/a/39042441/1199132【讨论】:
【参考方案2】:我终于找到了解决办法,谢谢你的帮助。
@ExtendWith(MockitoExtension.class)
public class ServiceImplTest
@InjectMocks
ServiceImpl service
@Spy
@InjectMocks
private Helper helper;
@Mock
private Repository repoMock;
@InjectMocks
private Helper helper;
这样,mocked repo 被注入到 spy helper 中,而 helper 可以被注入到 service 中。 @Spy 对象实际上是实例化的,所以如果你不存根它的任何方法,你将得到一个“真实”的对象。
这里,mocked repo 被注入到 helper 中,而 helper 被注入到 service 中。
【讨论】:
【参考方案3】:如果Repository
是一个接口(而不是具体类),您可以尝试以下操作:
@ExtendWith(MockitoExtension.class)
public class ServiceImplTest
@Spy
@InjectMocks
ServiceImpl service = new ServiceImpl();
@Mock
private Repository repoMock;
@InjectMocks
private Helper helper;
【讨论】:
问题依旧。在服务中使用 helper 时为 null,因为它没有正确注入(不是模拟) 实际上解决方案与您的解决方案很接近,但它是应该用@Spy注释的助手。【参考方案4】:我更喜欢构造函数注入而不是字段注入。 (阅读更多here)
在这种情况下,你的类看起来像这样:
@Component
public class Helper
@Autowired
public Helper(Repository repo)
this.repo = repo;
@Service
public class ServiceImpl
@Autowired
public ServiceImpl(Helper helper)
this.helper = helper;
通过这种方式,您可以使用模拟 Repository
对象轻松创建真正的 Helper
对象:
ServiceImpl service;
private Helper helper;
@Mock
private Repository repoMock;
@BeforeEach
void init()
helper = new Helper(repoMock);
service = new ServiceImpl(helper);
【讨论】:
我也更喜欢它,但不幸的是,我无法修改我正在测试的类以上是关于在服务测试中使用真实组件的主要内容,如果未能解决你的问题,请参考以下文章