使用 Mockito 在单元测试中使用具有@Required字段的类



我正在尝试对一个类进行单元测试;为了简洁起见,我们称之为Apple。它有一个@Required设置器,需要一个AppleManager豆子。AppleManager本身有一个比AppleStorageClientbean更@Required的二传手。我正在嘲笑AppleManager并将其注入Apple,但我还需要使用真正的AppleManager类来使用其AppleStorageClient对象中的方法检索数据。我怎样才能用Spring/Mockito来实现这一点?

测试:

public class AppleTest {
@InjectMocks
private Apple apple;
@Mock
private AppleManager appleManager;
????? 
private AppleManager realAppleManager;
//I tried = new AppleManager() here but the object is null...
//ostensibly because Spring doesn't know I want to use the bean
//also tried @Autowired to no avail
@Before
public void doBeforeStuff() {
MockitoAnnotations.initMocks(this);
}
...
}

源:

public class Apple {
private AppleManager appleManager;
@Required
public void setAppleManager(AppleManager appleManager) {
this.appleManager = appleManager;
}
....
}

&

public class AppleManager {
private AppleStorageClient appleStorageClient;
@Required
public void setAppleStorageClient() {
this.appleStorageClient = appleStorageClient;
}
...
}

总的来说,这里看起来有些东西"不完整"。我会解释为什么。

从技术上讲,如果您使用的是 spring-对我来说,这听起来不再像单元测试,可能是集成测试或其他东西。 单元测试通常应该非常非常快,启动 spring 不会让它们足够快地通过(想想在你的项目中有数千个单元测试,每个单元测试都在启动时运行 Spring - 它们需要很长时间才能完成)。

但让我们说它只是关于定义。当你在JUnit中使用spring测试框架时,必须有人启动并维护一个spring上下文来执行所有的依赖注入魔术并将其应用于测试用例。 在 Junit 实现中,需要一个特殊的运行器(JUnit 抽象):

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({ "classpath:my-test-context.xml" }) // or use Java Config

不过,这并没有出现在问题中。

所以现在春天创建一个上下文,并尝试注入豆子。我们已经有效地将我们的问题简化为具有两个接口实现的问题,并要求 spring 按接口注入实现,以便注入两个不同的实现。我可以在这里看到 2 种解决方案:

  1. 在春季之外创建一个模拟 - 无论如何,您可能不会指定您在春季的期望。春天只维护一个"真正的苹果经理">

  2. 在春季维护两者,但在测试用例中使用@Qualifier注释

现在我想强调的是,如果你维护真正的苹果管理器,它联系"苹果商店"(可能是一个数据库,具有驱动程序支持、事务管理等),你必须创建一个测试上下文,以便它能够连接到该数据库,如果苹果管理器通过 spring 在内部注入其依赖项, 那么这些豆子也必须被指定。

因此,如果将来要更改基础存储中的某些内容(例如,将驱动程序中的依赖项添加到另一个 Spring Bean,此测试上下文将自动中断)。只要意识到这一点并明智地注入豆子。

相关内容

  • 没有找到相关文章

最新更新