用Mockito模拟自动连接的依赖



我正在为一个使用Junit 5和Mockito 4的Spring项目编写单元测试。

我必须测试一个类,它通过构造函数接受2个对象,通过@Autowired接受另外2个对象。我需要模拟这4个对象,所以我在测试类中用@Mock注释了它们,然后用@InjectMocks注释了测试类。

我认为@InjectMocks会将我的4个mock注入到myService中,但它只注入了构造函数传递的2个,而其他2个是空的。

我正在寻找一个解决方案,不意味着在测试服务的变化。

测试的类看起来像这样:

@Service
public class MyService {
private String key = "KEY";
@Autowired
private FirstApiWrapper firstApiWrapper;
@Autowired
private SecondApiWrapper secondApiWrapper;
private MyRepository myRepository;
private OtherService otherService;
@Autowired
public MyService(
MyRepository myRepository,
OtherService otherService
) {
super();
this.myRepository = myRepository;
this.otherService = otherService;
}

我的测试类是这样的:

@ExtendWith(MockitoExtension.class)
public class MyServiceTest {
@Mock
MyRepository myRepository;
@Mock
OtherService otherService;
@Mock
FirstApiWrapper firstApiWrapper;
@Mock
SecondApiWrapper secondApiWrapper;
@InjectMocks
MyService myService;

你知道我的代码有什么问题吗?非常感谢大家!

——我也尝试了一些基于这个问题的东西:

@Mock
FirstApiWrapper firstApiWrapper;
@Mock
SecondApiWrapper secondApiWrapper;
@InjectMocks
MyService myService;
@BeforeEach
private void setUp() {
myService = new MyService(
Mockito.mock(MyRepository.class),
Mockito.mock(OtherService.class)
);
}

但是结果是完全一样的。此外,如果我删除存储库和服务实例,并尝试只注入包装器,它仍然失败!

我找到了一种不用重写现有代码就能解决这个问题的方法,方法是将下面的代码添加到测试类中:

@BeforeEach
private void setUp() {
MockitoAnnotations.openMocks(this);
}

但我不确定它是否"正确"。是这样的。

字段自动装配的一个问题是mockito将无法注入任何东西。那么,如果已经有了构造器注入,为什么还要混合不同的注入风格呢?

重写你的类:

@Service
public class MyService {
private String key = "KEY";
private final MyRepository myRepository;
private final OtherService otherService;
private final FirstApiWrapper firstApiWrapper;
private final SecondApiWrapper secondApiWrapper;
@Autowired // if its the only constructor in the class, you can omit @Autowired, spring will be able to call it anyway. You can even use Lombok to generate this constructor for, so you won't need to even write this method
public MyService(
MyRepository myRepository,
OtherService otherService,
FirstApiWrapper firstApiWrapper,
SecondApiWrapper secondApiWrapper
) {
this.myRepository = myRepository;
this.otherService = otherService;
this.firstApiWrapper = firstApiWrapper;
this.secondApiWrapper = secondApiWrapper;
}

有了这种设计,你可以在测试中安全地使用@Mock/@InjectMocks注释
Mockito将创建类的实例并注入相关的mock。

最新更新