Groovy spock测试用例失败,包括在我的测试用例中嵌入了Hazelcast

时间:2017-12-13 12:41:21

标签: java groovy mockito spock

我是Groovy spock测试框架的新手,尝试使用Groovy spock编写我的第一个测试。关于我的下面测试,我几乎没有问题,这是继续失败,没有得到什么改变代码,使其工作?

我在尝试的是什么?

  1. 我不理解的一件事是什么时候我应该使用mock,何时 我应该使用间谍
  2. 然后部分,我正在尝试致电classUnderTest.loadFromFile()以进行测试。
    总是我在CommonDataCache类中看到,实例变量hazelcastCache在调试测试时始终显示为null,但同时,我看到cache正在获取非空对象。由于这个原因,我总是得到空指针异常,如下面的错误日志所示。
  3. 请有人建议我为什么错过让它工作?

    错误日志:

    Members [1] {
        Member [127.0.0.1]:5001 - a43cbef2-ddf7-431b-9300-2b53c3ea9294 this
    }
    
    Dec 13, 2017 3:53:53 PM com.hazelcast.core.LifecycleService
    INFO: [127.0.0.1]:5001 [dev] [3.7.3] [127.0.0.1]:5001 is STARTED
    Dec 13, 2017 3:53:54 PM com.hazelcast.internal.partition.impl.PartitionStateManager
    INFO: [127.0.0.1]:5001 [dev] [3.7.3] Initializing cluster partition table arrangement...
    
    Condition not satisfied:
    
    commonDataCache.getFromCache("28ef4a8f-bfbc-4ad5-bc8a-88fd96ad82a8") != null
    |               |                                                    |
    |               null                                                 false
    com.realdoc.symphony.common.CommonDataCache@144ab54
    
    
        at com.realdoc.symphony.common.store.MemoryStoreManagerTest.populate hazlecast cache from symphony dat file(MemoryStoreManagerTest.groovy:65)
    
    Dec 13, 2017 3:53:54 PM com.hazelcast.instance.Node
    INFO: [127.0.0.1]:5001 [dev] [3.7.3] Running shutdown hook... Current state: ACTIVE
    

    这是我的Groovy测试类:

    import org.springframework.core.io.ClassPathResource
    import spock.lang.Specification
    import spock.lang.Subject
    
    import static io.dropwizard.testing.FixtureHelpers.fixture
    
    class MemoryStoreManagerTest extends Specification {
        /**
         * Mock the any config DTOs that carries static configuration data
         **/
        def dw = Mock(SymphonyConfig)
        def cacheConfig = Mock(CacheConfig)
    
        /**
         * This has to be spied because there is actual call happening in the target method which converts
         * json string format to MemoryStoreFileData DTO object
         */
        def jsonUtils = Spy(JsonUtils)
        def hazelcastInstance = TestHazelcastInstanceFactory.newInstance().newHazelcastInstance()
    
        /**
         * This class is under test
         **/
        @Subject
        def commonDataCache = new CommonDataCache(hazelcastInstance: hazelcastInstance,hazelcastCache: hazelcastInstance.getMap("default"), config: dw)
    
        /**
         * This class is under test
         **/
        @Subject
        def classUnderTest = new MemoryStoreManager(dw:dw, jsonUtils: jsonUtils, commonDataCache: commonDataCache)
    
        /**
         * Test whether populating symphony.dat file into hazelcast cache is working
         */
        def "populate hazlecast cache from symphony dat file"() {
    
            setup:
                def datFile = fixture("symphony.dat")
                def resource = new ClassPathResource("symphony.dat")
                def file = resource.getFile()
    
            when:
                cacheConfig.getStoreLocation() >> ""
                cacheConfig.getStoreFileName() >> "symphony.dat"
                dw.getUseHazelcastCache() >> true
                dw.getCacheConfig() >> cacheConfig
                cacheConfig.getFile() >> file
                commonDataCache.postConstruct()
    
            then:
                classUnderTest.loadFromFile()
    
            expect:
                commonDataCache.getFromCache("28ef4a8f-bfbc-4ad5-bc8a-88fd96ad82a8") != null
        }
    }
    

    这是我尝试测试loadFromFile()方法

    的目标类
    @Component
    public class MemoryStoreManager {
    
        private static final Logger LOG = LoggerFactory.getLogger(MemoryStoreManager.class);
    
    
        @Autowired
        SymphonyConfig dw;
    
        @Autowired
        JsonUtils jsonUtils;
    
        @Autowired
        CommonDataCache commonDataCache;
    
        private final Properties properties = new Properties();
    
        @PostConstruct
        public void loadFromFile() {
    
            File file = dw.getCacheConfig().getFile();
            LOG.info("Loading Data from file-{}", file.getAbsolutePath());
    
            FileInputStream inStream = null;
            try {
    
                if (!file.exists()) {
                    Files.createFile(file.toPath());
                }
    
                inStream = new FileInputStream(file);
                properties.load(inStream);
    
                String property = properties.getProperty("data");
    
                MemoryStoreFileData fileData;
    
                if (StringUtils.isNotEmpty(property)) {
                    fileData = jsonUtils.jsonToObject(property, MemoryStoreFileData.class);
                } else {
                    fileData = new MemoryStoreFileData(Collections.emptyMap(), Collections.emptyMap());
                }
    
                Long lastUpdatedTimeInFile = fileData.getLastUpdatedTime();
                LOG.info("Last updated time in File-{}", lastUpdatedTimeInFile);
                Long lastUpdatedTimeInCache = (Long) commonDataCache.getFromCache("lastUpdatedTime");
                LOG.info("Last updated time in Cache-{}", lastUpdatedTimeInCache);
    
                Map<String, DocData> loadedMap = fileData.getDocDataMap();
                if (MapUtils.isEmpty(loadedMap)) {
                    loadedMap = new HashMap<>();
                }
    
                Map<String, ProcessStatusDto> processStatusMap = fileData.getProcessStatusMap();
    
                if (MapUtils.isEmpty(processStatusMap)) {
                    processStatusMap = new HashMap<>();
                }
    
                if (lastUpdatedTimeInFile != null && (lastUpdatedTimeInCache == null || lastUpdatedTimeInCache < lastUpdatedTimeInFile)) {
                    LOG.info("Overwriting data from File");
                    commonDataCache.addAllToCache(loadedMap, processStatusMap);
                } else {
                    String requestId;
                    DocData fileDocData;
                    DocData cacheDocData;
                    Map<String, String> filePageStatusMap;
                    Map<String, String> cachePageStatusMap;
                    String pageId;
                    String fileStatus;
                    String cacheStatus;
                    for (Entry<String, DocData> entry : loadedMap.entrySet()) {
                        requestId = entry.getKey();
                        fileDocData = entry.getValue();
                        cacheDocData = (DocData) commonDataCache.getFromCache(requestId);
                        filePageStatusMap = fileDocData.getPageStatusMap();
                        cachePageStatusMap = cacheDocData.getPageStatusMap();
                        for (Entry<String, String> pageStatus : filePageStatusMap.entrySet()) {
                            pageId = pageStatus.getKey();
                            fileStatus = pageStatus.getValue();
                            cacheStatus = cachePageStatusMap.get(pageId);
    
                            if (StringUtils.equals("IN_PROCESS", cacheStatus) && !StringUtils.equals("IN_PROCESS", fileStatus)) {
                                cachePageStatusMap.put(pageId, fileStatus);
                                LOG.info("PageId: {} status: {} updated", pageId, fileStatus);
                            }
                        }
    
                        commonDataCache.addToCache(requestId, cacheDocData);
                    }
                }
    
            } catch (Exception e) {
                LOG.error("ErrorCode-{}, Component-{}, Message-{}. Error Loading cache data from file-{}. Exiting system", "OR-51010", "ORCHESTRATION", "Symphony cache loading exception", file.getAbsoluteFile(), e);
                System.exit(0);
            }
        }
    }
    

    这是我的缓存实用程序类,其中定义了存储和检索方法。

    @Component
    public class CommonDataCache {
    
        private static final Logger LOG = LoggerFactory.getLogger(CommonDataCache.class);
    
        @Autowired
        HazelcastInstance hazelcastInstance;
    
        @Autowired
        SymphonyConfig config;
    
        public static String LAST_UPDATED_TIME = "lastUpdatedTime";
        private IMap<String, Object> hazelcastCache = null;
        private boolean useHazelcast = false;
    
        private final Map<String, Object> cache = new ConcurrentHashMap<>();
    
        @PostConstruct
        public void postConstruct() {
            hazelcastCache = hazelcastInstance.getMap("default");
    
            // Enable only if logging level is DEBUG
            if (LOG.isDebugEnabled()) {
                hazelcastCache.addEntryListener(new HazelcastMapListener(), true);
            }
            useHazelcast = config.getUseHazelcastCache();
        }
    
        public Map<String, Object> getAllDataFromCache() {
            return hazelcastCache;
        }
    
        public void addToCache(String key, Object value) {
            if (useHazelcast) {
                hazelcastCache.put(key, value);
                hazelcastCache.put(LAST_UPDATED_TIME, System.currentTimeMillis());
            } else {
                cache.put(key, value);
                cache.put(LAST_UPDATED_TIME, System.currentTimeMillis());
            }
        }
    
        public Object getAndRemoveFromCache(String key) {
            if (useHazelcast) {
                return hazelcastCache.remove(key);
            } else {
                return cache.remove(key);
            }
        }
    
        public Object getFromCache(String key) {
            if (useHazelcast) {
                return hazelcastCache.get(key);
            } else {
                return cache.get(key);
            }
        }
    
        /**
         * 
         * @param cacheDataMap
         */
        public void addAllToCache(Map<String, DocData> cacheDataMap, Map<String, ProcessStatusDto> processStatusMap) {
            hazelcastCache.putAll(cacheDataMap);
            hazelcastCache.putAll(processStatusMap);
            hazelcastCache.put(LAST_UPDATED_TIME, System.currentTimeMillis());
        }
    
        public void lockKey(String key) {
            if (useHazelcast) {
                hazelcastCache.lock(key);
            }
        }
    
        public void unlockKey(String key) {
            if (useHazelcast) {
                hazelcastCache.unlock(key);
            }
        }
    
        public Map<String, Object> getByKeyContains(String keyString) {
    
            Map<String, Object> values;
            if (useHazelcast) {
                Set<String> foundKeys = hazelcastCache.keySet(entry -> ((String)entry.getKey()).contains(keyString));
                values = hazelcastCache.getAll(foundKeys);
            } else {
                values = Maps.filterEntries(cache, entry -> entry.getKey().contains(keyString));
            }
            return values;
        }
    
    }
    

    这是groovy测试的maven依赖项。

            <!-- Dependencies for GROOVY TEST -->
            <dependency>
                <groupId>com.hazelcast</groupId>
                <artifactId>hazelcast</artifactId>
                <version>${hazelcast.version}</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>com.hazelcast</groupId>
                <artifactId>hazelcast</artifactId>
                <version>${hazelcast.version}</version>
                <classifier>tests</classifier>
                <scope>test</scope>
            </dependency>
            <!-- GROOVY TEST FRAMEWORK -->
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjweaver</artifactId>
                <version>${aspectj.version}</version>
            </dependency>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>${junit.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-test</artifactId>
                <version>${org.springframework.version}</version>
            </dependency>
    
            <dependency>
                <groupId>io.dropwizard</groupId>
                <artifactId>dropwizard-core</artifactId>
            </dependency>
            <dependency>
                <groupId>io.dropwizard</groupId>
                <artifactId>dropwizard-assets</artifactId>
            </dependency>
    
            <dependency>
                <groupId>io.dropwizard</groupId>
                <artifactId>dropwizard-testing</artifactId>
                <scope>test</scope>
            </dependency>
    
            <dependency>
                <groupId>realdoc</groupId>
                <artifactId>dropwizard-spring</artifactId>
                <version>${realdoc.dropwizard-spring.version}</version>
            </dependency>
    
            <dependency>
                <groupId>org.codehaus.groovy</groupId>
                <artifactId>groovy-all</artifactId>
                <!-- any version of Groovy \>= 1.5.0 should work here -->
                <version>${groovy-all.version}</version>
                <!--<scope>test</scope>-->
            </dependency>
            <dependency>
                <groupId>org.spockframework</groupId>
                <artifactId>spock-core</artifactId>
                <version>${spock.version}</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.spockframework</groupId>
                <artifactId>spock-spring</artifactId>
                <version>${spock.version}</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>cglib</groupId>
                <artifactId>cglib-nodep</artifactId>
                <version>${cglib-nodep.version}</version>
                <scope>test</scope>
            </dependency>
            <!-- GROOVY TEST FRAMEWORK -->
    
    
    
            <build>
            <testSourceDirectory>src/test/groovy</testSourceDirectory>
            <testResources>
                <testResource>
                    <directory>src/test/resources</directory>
                    <filtering>true</filtering>
                </testResource>
            </testResources>
            ...
            ...
            </build>
    

0 个答案:

没有答案