我想测试一个具有" ObjectMapper"的类。作为实例变量:
public class EventTransformerImpl implements EventTransformer {
@Inject
private ObjectMapper objectMapper;
private String convertParametersToJson(NotificationConfig config) {
String parametersAsJson = null;
try {
parametersAsJson = objectMapper.writeValueAsString(config.getOrdinaryParameters());
} catch (IOException e) {
logger.info("There was a problem in writing json:" + config.getParameters(), e);
parametersAsJson = null;
}
return parametersAsJson;
}
}
这个班级没有任何" setter"或"构造函数"用于初始化" objectMapper" (它使用" spring"初始化):
<bean id="objectMapper" class="com.fasterxml.jackson.databind.ObjectMapper">
<property name="dateFormat">
<bean class="java.text.SimpleDateFormat">
<constructor-arg value="yyyy-MM-dd'T'HH:mm:ssZ"/>
</bean>
</property>
</bean>
当我想测试&#34; EventTransformerImpl&#34; class,objectMapper有null值,我怎样才能传递&#34; objectMapper&#34; to&#34; EventTransformerImpl&#34;在我的单元测试课程中。
答案 0 :(得分:3)
这是一个典型的示例,其中模拟框架(例如Mockito)可以帮助您:
public class TestClass {
@Mock
private ObjectMapper objectMapper;
@InjectMocks
private EventTransformer eventTransformer;
@BeforeMethod
public void setUp() {
eventTransformer = new EventTransformerImpl();
MockitoAnnotations.initMocks(this);
}
}
此处,@Mock
和@InjectMocks
是Mockito框架的一部分。魔术发生在MockitoAnnotations.initMocks(this)
,会扫描this
,在这种情况下为TestClass
,用于这些注释。 Mockito将objectMapper
初始化为模拟,并将其注入eventTransformer
。然后,您可以使用Mockito来决定objectMapper
的行为方式。
您可以阅读有关Mockito here的更多信息。
此外,@BeforeMethod
是一个TestNG方法,类似于JUnits @Before
。
然而,许多人更喜欢constructor injection提出的davidxxx。这将使哪个依赖项EventTransformerImpl
更清楚,并强制使用正确的依赖项进行初始化。通过这样做,没有必要&#34;神奇地&#34; (我猜Mockito在引擎盖下使用反射)注入依赖项,只需通过调用构造函数初始化要测试的类。
你的课可能看起来像这样(这里使用的是Spring {#1}}注释):
@Autowired
这样不容易出错,因为对于public class EventTransformerImpl implements EventTransformer {
private ObjectMapper objectMapper;
@Autowired
public EventTransformerImpl(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
private String convertParametersToJson(NotificationConfig config) {
String parametersAsJson = null;
try {
parametersAsJson = objectMapper.writeValueAsString(config.getOrdinaryParameters());
} catch (IOException e) {
logger.info("There was a problem in writing json:" + config.getParameters(), e);
parametersAsJson = null;
}
return parametersAsJson;
}
}
,如果失败,Mockito会默默地忽略注入,而调用构造函数则会让测试类完全控制测试的初始化。
答案 1 :(得分:1)
1)一个类应该是自然可测试的:为什么不在EventTransformerImpl
中添加构造函数来注入映射器?
您可以在弹簧配置中执行类似的操作:
<bean id="EventTransformer" class="EventTransformerImpl">
<constructor-arg ref="objectMapper"/>
</bean>
在测试中,您可以在构造函数中使用EventTransformerImpl
模拟的依赖项实例化ObjectMapper
。
2)另一种解决方案是使用反射在测试方法中将测试中的场注入。
你可以使用ReflectionTestUtils
类的public static final void injectValue(String fieldName, Object fieldValue, Object targetObject) {
try {
Field f = targetObject.getClass().getDeclaredField(fieldName);
f.setAccessible(true);
f.set(targetObject, fieldValue);
} catch (Exception e) {
// handle the exception
}
}
类来设置依赖关系,或者如果你没有使用Spring,你可以编写一个简单的实用工具方法来完成这项工作:
http://192.168.0.10/set_camprop.cgi?com=setlist
答案 2 :(得分:1)
为了在JUnit测试和其他依赖的对象中注入Spring依赖项,我使用
SELECT * FROM OPENQUERY ([DVT-FUSION],
'EXEC CRM_DVT.dbo.SP_RPT_Billing_Summary ''R1'', ''R2'', ''0'', ''0'' ')
您也可以提供代码bean初始化
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:testBeans.xml" })
public class TestRunner {
@Test
public void test1() {
在https://www.mkyong.com/unittest/junit-spring-integration-example/
了解详情答案 3 :(得分:1)
这三个答案都很好;所以我不需要重复那些细节,但我认为值得在“完整”图片上“对齐”。
如图所示 Spring 内置了为单元测试进行注入的方法;你可以继续前进并使用它。但是,当然,这意味着您将业务逻辑代码更“耦合”到Spring框架。
因此,如果你考虑在非Spring情况下重新使用你的代码,那么你会发现不仅你的生产代码,而且你的单元测试需要重大的返工才能在没有Spring的情况下使用。
因此,在其他两个答案中有一些优点,建议更改您的生产代码,以便您至少可以完全测试您的生产代码,而无需在此处向Spring添加依赖项。