Expo TypeError 的笑话模拟权限:无法读取未定义的属性“askAsync”

Posted

技术标签:

【中文标题】Expo TypeError 的笑话模拟权限:无法读取未定义的属性“askAsync”【英文标题】:Jest Mocking Permissions of Expo TypeError: Cannot read property 'askAsync' of undefined 【发布时间】:2019-10-19 20:33:51 【问题描述】:

我在嘲笑 expo 和 Permissions 模块,但是在调用 Permissions.AskAsync Permissions 时未定义。

问题看起来像这个问题。 Using Jest to mock named imports

使用了提供的答案,但没有用。

我已经嘲笑了 axios,它有效。对 expo 模块做同样的事情是行不通的。

我要测试的功能:

    checkPermission = async () => 


        const statusCamera = await Permissions.askAsync(Permissions.CAMERA);

        // console.log(statusCamera);

        this.setState(cameraPermission: statusCamera);

        const statusCameraRoll = await Permissions.askAsync(Permissions.CAMERA_ROLL);
        this.setState(cameraRollPermission: statusCameraRoll);
    ;

测试:

describe("Test the Permission function", () => 
    it('should return rejected permission.', async function () 
        const wrapper = shallow(<Photo2/>);
        const instance = wrapper.instance();

        await instance.checkPermission();

        expect(instance.state("cameraPermission")).toBeFalsy();
    );
);

我用于博览会的模拟:

jest.mock('expo', ()=>(
  Permissions: 
     askAsync: jest.fn()
  
))

并尝试过 (在 mocks/expo.js 文件中)

export default 
    Permissions: 
        askAsync: jest.fn(() => 
            return "SOMETHING"
        )

    

并尝试过 (在 mocks/expo.js 文件中)

jest.mock('expo', ()=>(
    Permissions: 
        askAsync: jest.fn()
    
));

错误:“TypeError:无法读取未定义的属性‘askAsync’”

此错误发生在调用Permissions.askAsyc 的行上。所以权限是未定义的。 (也检查了console.log(Permissions)

我预计 instance.state("cameraPermission") 是虚假的,但它在到达该行之前就崩溃了。

【问题讨论】:

【参考方案1】:

由于 expo 将包更改为import * as Permissions from 'expo-permissions';

您只需要创建“mocks/expo-permissions.js”并拥有它:

export const getAsync = jest.fn(permissions => Promise.resolve());
export const askAsync = jest.fn(permissions => Promise.resolve());

【讨论】:

【参考方案2】:

teerryn's answer 是正确的,是一个好的开始。添加更多细节:

    除非您为 Jest 配置了不同的 roots,否则您应该将模拟文件放在 __mocks__/expo-permissions.js 中,其中 __mocks__ 是与您的 node_modules 文件夹处于同一级别的目录。请参阅 mocking node modules 上的 Jest 文档。 由于我们模拟模块的方式,传入的permissions 参数将是未定义的,因此您需要模拟要使用的权限类型。只需要像export const CAMERA_ROLL = 'camera_roll'; 这样简单的东西 如果您想根据传入的权限类型做出不同的响应(例如,允许Permissions.CAMERA 但拒绝Permissions.CAMERA_ROLL 和所有其他类型),您可以模拟askAsync 函数的实现。例如,您的 __mocks__/expo-permissions.js 文件如下所示:
export const CAMERA = 'camera';
export const CAMERA_ROLL = 'camera_roll';
export const askAsync = jest.fn().mockImplementation((permissionType) => 
  const responseData = permissionType === CAMERA ?  status: 'granted'  :  status: 'undetermined' ; // you could also pass `denied` instead of `undetermined`
  return Promise.resolve(responseData);
);

【讨论】:

【参考方案3】:

问题是您处理异步测试不正确(您的 checkPermission() 函数是异步的)。有几种方法可以告诉你要测试异步函数。 Here are a few ways.

这里是您问题的快速解决方案:

...

import  Permissions  from 'expo';

...

jest.mock('expo', () => (
    Permissions: 
        askAsync: jest.fn(),
    
));

...

describe("Test the Permission function", () => 
    it('should return rejected permission.', () => 
        Permissions.askAsync.mockImplementation( permission =>  return status: 'granted';  ); // if you want to add some sort of custom functionality

        const wrapper = shallow(<Photo2/>);
        const instance = wrapper.instance();

        return instance.checkPermission().then(data => 
            expect(instance.state("cameraPermission")).toBeFalsy();
        );
    );
);

【讨论】:

以上是关于Expo TypeError 的笑话模拟权限:无法读取未定义的属性“askAsync”的主要内容,如果未能解决你的问题,请参考以下文章

笑话:TypeError:无法读取未定义的属性“变量”

反应笑话单元测试用例TypeError:无法读取未定义的属性'then'

Expo 网络响应超时,无法在 Android 模拟器上运行 Expo 应用

react-native expo android macos问题

“TypeError:无法读取未定义的属性‘应用’”

无法在 Expo CLI 模拟器上运行 React Native App