JUnit、Mockito 和 Spring ApplicationContext:模拟属性时遇到问题
Posted
技术标签:
【中文标题】JUnit、Mockito 和 Spring ApplicationContext:模拟属性时遇到问题【英文标题】:JUnit, Mockito and Spring ApplicationContext: Trouble mocking a property 【发布时间】:2017-01-24 13:10:52 【问题描述】:问题描述:我无法为特定的 spring bean 设置一个模拟来返回我的开发框上的正确模拟测试资源位置,而不是运行时 Web 应用程序根。我确信我的重构做了一些愚蠢的事情。我希望有人看到它。
我正在使用 Quartz 在 Spring 上执行作业。 Quartz 工作运行良好,并且可以正常获取 Spring 应用程序上下文。剩下的唯一事情就是为 Web 资源所在的测试或运行时位置连接一个配置属性。 :
JUnit 4、Spring 3.1、Quartz、Java 8、Mockito
界面:
public interface ITitle
/**
* Gets the root of the application.
* @return location String
*/
public String getRuntimeLocation();
实现:
@Component("Title")
public class Title implements ITitle, ApplicationContextAware
private String location;
/**
* Gets the root of the application.
* @return location String
*/
public String getRuntimeLocation()
String location = "";
config = getConfig();
log.debug("Class Title --- Method getRuntimeLocation -- config is " + config );
location = config.getRuntimeLocation();
log.debug("Class Title --- Method getRuntimeMethod -- runtime location is " + location );
return location;
单元测试
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.generators.analytics.serialised.ITitle;
import java.io.File;
import static org.junit.Assert.assertNotNull;
import static org.mockito.Mockito.when;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations =
"classpath*:/WEB-INF/conf/analytics-context.xml"
)
public class GeneratorTest
private AnalyticsGenerator generator;
@Mock
private IConfig config;
@Mock
private ApplicationContext applicationContext;
@Mock
private ITitle title;
// Set a logger
private static Logger log = LoggerFactory.getLogger(GeneratorTest.class);
private JobExecutionContext job;
/**
* Initialises the test parameters.
*/
@Before
public void setUp() throws Exception
//create a generator object
generator = new AnalyticsGenerator();
MockitoAnnotations.initMocks(this);
when(applicationContext.getBean("Query")).thenReturn(query);
when(applicationContext.getBean("Config")).thenReturn(config);
when(config.getRuntimeLocation()).thenReturn(“/Users/me/dev/workarea/");
generator.executeInternal(ctx);
/**
* Expected: Json exists
*/
@Test
public void testThatExecuteInternalCreatesAJsonFile() throws JobExecutionException
generator.executeInternal(job);
File returnedJson = new File("classpath:/google-analytics.json");
Assert.assertNotNull("The JSON file does not exist", returnedJson );
/**
* Remove objects from memory.
*/
@After
public void tearDown() throws Exception
generator = null;
spring xml 文件
<?xml version="1.0" encoding="UTF-8"?>
<!--
* analytics-context.xml
*
* resource configuration file for Google Analytics recommendations integration framework.
*
* All custom beans and services must be defined in this file.
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:ehcache="http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.2.xsd
http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring
http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring/ehcache-spring-1.1.xsd">
<context:annotation-config/>
<!--
START Globally used Google Analytics Query parameters
-->
<bean id="Config" class=“com.generators.analytics.Config">
<property name="reportLocation" value="/data/runtime/web/assets/generated-list/google-analytics.json"/>
<property name="runtimeLocation" value="/data/runtime/web/"/>
</bean>
<bean id="configFactory" class="org.springframework.beans.factory.config.ServiceLocatorFactoryBean">
<property name="serviceLocatorInterface" value=“com.generators.analytics.ConfigFactory" />
</bean>
<alias name="Config" alias="C" />
<bean id="Title" class=“com.generators.analytics.serialised.Title">
<property name="config" ref="Config"/>
</bean>
<context:component-scan base-package=“com.generators.analytics" />
<!--
END Globally used Google Analytics Query parameters
-->
运行测试后,我在日志中得到了这个:
11:51:43.020 [main] DEBUG com.generators.analytics.serialised.Title - Class Title --- Method getConfig -- applicationContext is org.springframework.context.support.GenericApplicationContext@57f23557: startup date [Tue Jan 24 11:51:31 GMT 2017]; root of context hierarchy
11:51:43.020 [main] DEBUG com.generators.analytics.serialised.Title - Class Title --- Method getConfig -- config is com.generators.analytics.Config@13d9cbf5
11:51:43.020 [main] DEBUG com.generators.analytics.serialised.Title - Class Title --- Method getRuntimeLocation -- config is com.generators.analytics.Config@13d9cbf5
11:51:43.020 [main] DEBUG com.generators.analytics.serialised.Title - Class Title --- Method getRuntimeMethod -- runtime location is /data/runtime/web/
问题是,我在获取预期路径 /Users/me/dev/workarea/ 方面有什么明显的错误吗?
我想我需要进行重构以从方法中提取位置?我不确定如何重构这个特定的步骤。
when(config.getRuntimeLocation()).thenReturn(“/Users/me/dev/workarea/");
【问题讨论】:
【参考方案1】:我通过创建 spring 配置文件的副本并更改来解决了这个问题
<bean id="Config" class="com.generators.analytics.Config">
<property name="reportLocation" value="/Users/arnout/dev/soton-test/workarea/assets/generated-list/google-analytics.json"/>
<property name="runtimeLocation" value="/Users/arnout/dev/soton-test/workarea/"/>
</bean>
然后改变
@ContextConfiguration(locations =
"classpath*:/WEB-INF/conf/livesite_customer/resources/test-analytics-resource-config.xml"
)
public class GeneratorTest
在阅读了 Spring 配置中的 Profiles 之后,我做了一些横向思考。实际上我不需要配置文件,这就像在测试模式下进行另一个弹簧配置一样简单。
【讨论】:
【参考方案2】:在 ApplicationContext 中使用 @MockBean 而不是 @Mock 怎么样?
我相信你的 ApplicationContext 类是由@Autowired 在你的实际类中创建的。
【讨论】:
以上是关于JUnit、Mockito 和 Spring ApplicationContext:模拟属性时遇到问题的主要内容,如果未能解决你的问题,请参考以下文章
Spring 集成框架中 ResponseEntity<?> 的 Junit Mockito 测试用例
在spring中简单使用Mockito解决Bean依赖树问题