@Mock 和 @InjectMocks 之间的差异
在测试类中,被测试的类应该使用@InjectMocks
进行注解。这告诉Mockito需要将模拟对象注入到哪个类中:
private SomeManager someManager;
从此以后,我们可以指定类中的具体方法或对象,比如在这个例子中,SomeManager
类中的SomeDependency
对象将被替换为模拟对象:
private SomeDependency someDependency;
在这个例子中,SomeManager
类中的SomeDependency
对象将被模拟。
但是,如果someManager
有多个构造函数,这样的方法还能正常工作吗?如果someManager
有5个构造函数,它如何知道你想要使用哪一个?
当使用@InjectMocks
注解时,Mockito会尝试使用默认构造函数来实例化被测试类的对象。如果被测试类有多个构造函数,且没有默认构造函数,那么就会抛出异常。为了解决这个问题,你可以在被测试类的构造函数上使用@Inject
注解,以告诉Mockito使用哪个构造函数来实例化对象。例如,如果SomeManager
类有5个构造函数,你可以使用以下代码来指定要使用的构造函数:
@InjectMocks private SomeManager someManager; @Inject public SomeManager(SomeDependency someDependency) { this.someDependency = someDependency; }
通过在构造函数上使用@Inject
注解,你可以告诉Mockito使用带有SomeDependency
参数的构造函数来实例化SomeManager
对象。这样,Mockito就能正确地注入模拟对象。
@Mock和@InjectMocks之间的区别
在进行单元测试时,我们经常需要模拟对象或注入依赖项。Mockito是一个流行的Java框架,用于创建和管理模拟对象。在Mockito中,@Mock和@InjectMocks是两个常用的注解,用于创建和注入模拟对象。
在上面的示例代码中,我们有一个Game类和一个Player类。Game类依赖于Player类来执行attack方法。我们可以使用@Mock注解来模拟Player类,并使用when和thenReturn方法定义它的行为。最后,使用@InjectMocks注解将模拟的Player对象注入到Game类中。
Mockito在注入模拟对象时,会根据类的类型签名来匹配依赖项。因此,即使属性名不同,我们仍然可以使用@InjectMocks注解注入依赖项。
然而,有时候我们需要注入的依赖项本身也有依赖关系。例如,在上面的示例代码中,如果weapon实际上是一个类而不是一个字符串,该怎么办?
对于这种情况,我们可以使用@Spy注解来创建一个真实的对象,并使用@InjectMocks注解将其注入到需要的类中。这样,我们可以在创建依赖项时进行依赖注入。
总结起来,@Mock用于创建和管理模拟对象,@InjectMocks用于注入依赖项。通过使用这两个注解,我们可以更好地进行单元测试,并确保依赖项的正确注入。
注:该问题和解决方法摘自stackoverflow.com的评论。
@Mock和@InjectMocks之间的区别是什么?这个问题的出现是因为有人想知道这两个注解的作用和用法。下面是关于这个问题的一些讨论和解决方法。
首先,@Mock注解用于创建一个模拟对象,而@InjectMocks注解用于创建一个类的实例并将使用@Mock或@Spy注解创建的模拟对象注入到该实例中。
使用这两个注解时,需要使用(MockitoJUnitRunner.class)或Mockito.initMocks(this)来初始化这些模拟对象并注入它们(适用于JUnit 4)。而对于JUnit 5,需要使用(MockitoExtension.class)。
例如,在JUnit 4中的测试代码如下所示:
(MockitoJUnitRunner.class) // JUnit 4 public class SomeManagerTest { private SomeManager someManager; private SomeDependency someDependency; // this will be injected into someManager // tests... }
这段代码中,SomeDependency对象将被注入到SomeManager实例中。
然而,注入模拟对象只适用于直接成员,不能递归注入。但是可以使用深度存根(deep stubs)来设置模拟对象以允许递归调用。
此外,Mockito.initMocks(this)方法已经被标记为弃用,应该使用Mockito.openMocks(this)方法来代替。
对于JUnit 5,如果测试类使用了@ExtendWith(MockitoExtension.class)注解,那么不需要使用(MockitoJUnitRunner.class)或Mockito.initMocks(this)来初始化模拟对象。
当然,还有一些其他的讨论和问题。例如,某些情况下无法通过注解提供一些无法由注解提供的项,如上下文。对于这种情况,可以通过其他方式来提供所需的项。
还有一位用户提到使用(MockitoExtension.class)时出现了异常。这可能是因为存在不必要的存根(UnnecessaryStubbingException)。可以通过删除不必要的存根或使用'lenient'严格度来解决这个问题。
@Mock和@InjectMocks是用于创建和注入模拟对象的注解。它们可以帮助我们在单元测试中模拟依赖对象,并将它们注入到被测试类的实例中。虽然它们在使用上有一些限制和注意事项,但它们是编写清晰和可维护的测试代码的有用工具。