2016-12-03 73 views
8

我正在用React Native构建一个应用程序。我想尽量减少与数据库通信的频率,所以我大量使用AsyncStorage。尽管DB和AsyncStorage之间的转换中存在大量的错误空间。因此,我想确保AsyncStorage具有我认为通过针对它运行自动化测试的数据。令人惊讶的是,我还没有找到任何有关如何在网上做的信息。我自己做的尝试还没有解决。如何使用Jest测试异步存储?

使用玩笑:

it("can read asyncstorage",() => { 
return AsyncStorage.getItem('foo').then(foo => { 
    expect(foo).not.toBe(""); 
}); }); 

这种方法失败,出现错误:

TypeError: RCTAsyncStorage.multiGet is not a function 

卸下回报会使其无需等待值立刻运行,并且不恰当地通过测试。

我腹背受敌完全相同的错误,当我试图测试其使用的await关键字:

it('can read asyncstorage', async() => { 
this.foo = ""; 
await AsyncStorage.getItem('foo').then(foo => { 
    this.foo = foo; 
}); 
expect(foo).not.toBe(""); }); 

如何成功运行针对AsyncStorage价值主张有什么建议?我宁愿继续使用Jest,但是如果它只能用一些替代测试库来完成,那么我可以使用它。

回答

5

我原来的答复只是指了指react-native-simple-store的作者如何处理了嘲讽。我用我自己的嘲笑更新了我的答案,这消除了Jason的硬编码模拟反应。

Jason Merinohttps://github.com/jasonmerino/react-native-simple-store/blob/master/tests/index-test.js#L31-L64

jest.mock('react-native',() => ({ 
AsyncStorage: { 
    setItem: jest.fn(() => { 
     return new Promise((resolve, reject) => { 
      resolve(null); 
     }); 
    }), 
    multiSet: jest.fn(() => { 
     return new Promise((resolve, reject) => { 
      resolve(null); 
     }); 
    }), 
    getItem: jest.fn(() => { 
     return new Promise((resolve, reject) => { 
      resolve(JSON.stringify(getTestData())); 
     }); 
    }), 
    multiGet: jest.fn(() => { 
     return new Promise((resolve, reject) => { 
      resolve(multiGetTestData()); 
     }); 
    }), 
    removeItem: jest.fn(() => { 
     return new Promise((resolve, reject) => { 
      resolve(null); 
     }); 
    }), 
    getAllKeys: jest.fn(() => { 
     return new Promise((resolve) => { 
      resolve(['one', 'two', 'three']); 
     }); 
    }) 
    } 
})); 

一个不错的简单的方法来这是我自己的模拟:

const items = {}; 

jest.mock('react-native',() => ({ 

AsyncStorage: {   

    setItem: jest.fn((item, value) => { 
     return new Promise((resolve, reject) => {   
    items[item] = value; 
      resolve(value); 
     }); 
    }), 
    multiSet: jest.fn((item, value) => { 
     return new Promise((resolve, reject) => { 
    items[item] = value; 
      resolve(value); 
     }); 
    }), 
    getItem: jest.fn((item, value) => { 
     return new Promise((resolve, reject) => { 
      resolve(items[item]); 
     }); 
    }), 
    multiGet: jest.fn((item) => { 
     return new Promise((resolve, reject) => { 
      resolve(items[item]); 
     }); 
    }), 
    removeItem: jest.fn((item) => { 
     return new Promise((resolve, reject) => { 
      resolve(delete items[item]); 
     }); 
    }), 
    getAllKeys: jest.fn((items) => { 
     return new Promise((resolve) => { 
      resolve(items.keys()); 
     }); 
    }) 
    } 
})); 
+0

此解决方案仅适用于您的用例,下面的解决方案应该是可接受的解决方案! – Ouadie

+0

@Ouadie它需要编辑,以便定义'multiGet'和'multiSet'。 @布赖恩案特别询问'multiGet'。我会挖掘我如何最终嘲笑我的,避免硬编码的响应'resolve()' – jaygooby

+0

在我的测试中使用你的'测试'时'从'react-native-implementation.js''找不到模块'AsyncStorage''模拟 - 任何想法为什么? :) @jaygooby – jhm

12

可能是你可以尝试这样的事:

mockStorage.js

export default class MockStorage { 
    constructor(cache = {}) { 
    this.storageCache = cache; 
    } 

    setItem = jest.fn((key, value) => { 
    return new Promise((resolve, reject) => { 
     return (typeof key !== 'string' || typeof value !== 'string') 
     ? reject(new Error('key and value must be string')) 
     : resolve(this.storageCache[key] = value); 
    }); 
    }); 

    getItem = jest.fn((key) => { 
    return new Promise((resolve) => { 
     return this.storageCache.hasOwnProperty(key) 
     ? resolve(this.storageCache[key]) 
     : resolve(null); 
    }); 
    }); 

    removeItem = jest.fn((key) => { 
    return new Promise((resolve, reject) => { 
     return this.storageCache.hasOwnProperty(key) 
     ? resolve(delete this.storageCache[key]) 
     : reject('No such key!'); 
    }); 
    }); 

    clear = jest.fn((key) => { 
    return new Promise((resolve, reject) => resolve(this.storageCache = {})); 
    }); 

    getAllKeys = jest.fn((key) => { 
    return new Promise((resolve, reject) => resolve(Object.keys(this.storageCache))); 
    }); 
} 

和你测试文件内:

import MockStorage from './MockStorage'; 

const storageCache = {}; 
const AsyncStorage = new MockStorage(storageCache); 

jest.setMock('AsyncStorage', AsyncStorage) 

// ... do things 
+1

尽管试图从'react-native'中导入它,但'从'myFileName.js'中找不到模块'AsyncStorage' - 任何想法? :) – jhm

+0

应该接受答案,因为它最清楚地回答了原点问题 – mcabe

-1

对于其他任何人都可以来到这里,asyncStorage也需要一个回调,一些库使用此