Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

单元测试 #3359

Closed
Gamehu opened this issue Jul 23, 2020 · 17 comments
Closed

单元测试 #3359

Gamehu opened this issue Jul 23, 2020 · 17 comments
Assignees

Comments

@Gamehu
Copy link

Gamehu commented Jul 23, 2020

Do you want to request a feature or report a bug?
feature
What is the current behavior?
基于iceworks创建的项目,按照ice的方式创建了services+models+components,现在想要测试services等文件夹下的内容

jest示例
`import listService from '../../services/list'

test('SearchInput tag selector', () => {
const data = listService.fetchList()
expect(data).not.toBeNull
})
`

  • icejs version:6.14.6
  • Node verson:12.18.2

What is the expected behavior?

"test": "icejs test --jest-coverage",
运行测试:npm run test

`
Test suite failed to run

Cannot find module '$ice/history' from 'history.ts'

However, Jest was able to find:
    '../xxxxxxx/.ice/history.ts'

You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js', 'json', 'jsx', 'ts', 'tsx', 'node'].

See https://jestjs.io/docs/en/configuration#modulefileextensions-array-string

However, Jest was able to find:
    '../xxxxxx/.ice/runtimeModule.tsx'

You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js', 'json', 'jsx', 'ts', 'tsx', 'node'].

See https://jestjs.io/docs/en/configuration#modulefileextensions-array-string

However, Jest was able to find:
    '..xxx/.ice/createApp.tsx'

You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js', 'json', 'jsx', 'ts', 'tsx', 'node'].

See https://jestjs.io/docs/en/configuration#modulefileextensions-array-string

However, Jest was able to find:
    '../xxxx/services/list.jsx'
You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js', 'json', 'jsx', 'ts', 'tsx', 'node'].

See https://jestjs.io/docs/en/configuration#modulefileextensions-array-string

> 1 | import {
    | ^
  2 |   createBrowserHistory,
  3 |   createHashHistory,
  4 |   createMemoryHistory,

  at Resolver.resolveModule (node_modules/@alib/build-scripts/node_modules/jest-resolve/build/index.js:259:17)
  at Object.<anonymous> (.ice/history.ts:1:1)

`

怎么才能测试services下面的方法以及components下的组件

@Gamehu
Copy link
Author

Gamehu commented Jul 23, 2020

直接跑单元测试也无法引入ice

import { request } from 'ice'
const mockId = '00000000-0d00-0000-0000-000000000000'
async function fetchList(params) {
	return await request.post('/api/v1/domain/xxxx', {
		...params,
		id: mockId,
	})
}
test('getResources', () => {
	const data=fetchList();
	expect(data).not.toBeNull;
})

结果:

  ● Test suite failed to run

    Cannot find module 'ice' from 'ice.request.test.js'

    However, Jest was able to find:
    	'../D:/xxx/test/components/IceRequest/ice.request.test.js'

    You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js', 'json', 'jsx', 'ts', 'tsx', 'node'].

    See https://jestjs.io/docs/en/configuration#modulefileextensions-array-string

    > 1 | import { request } from 'ice'
        | ^
      2 | const mockId = '00000000-0d00-0000-0000-000000000000'
      3 | async function fetchList(params) {
      4 | 	return await request.post('/api/v1/domain/xxxx', {

      at Resolver.resolveModule (node_modules/jest-resolve/build/index.js:259:17)
      at Object.<anonymous> (test/components/IceRequest/ice.request.test.js:1:1)

@LanceZhu
Copy link
Collaborator

@chenbin92
生成 jest 配置时 moduleNameMapper 需要将 $ice/history 中的 $ 转义下。Webpack 中以 $ 开头的 alias 均需转义下。

现有 jest 配置:

// jest.config.js
{
	moduleNameMapper: {
		"^$ice/history$": 'historypath' // 转换成正则表达式为 /^$ice/history$/,无法匹配到 '$ice/history'
	}
}

预期 jest 配置:

// jest.config.js
{
	moduleNameMapper: {
-		'^$ice/history$': 'history/path'
+		'^\\$ice/history$': 'historypath' // 转换成正则表达式为 /^\$ice/history$/,可匹配到 '$ice/history'
	}
}

对应代码:
build-scripts /lib/commands/test.js 54 行

@LanceZhu
Copy link
Collaborator

@Gamehu
暂时可在 jest 配置文件中添加对应的 moduleNameMapper 试下,即:

// ./jest.config.js
{
	// ... 其它配置
	moduleNameMapper: {
		'^\\$ice/history$': './router/history'
	}
}

@chenbin92
Copy link
Collaborator

@Gamehu 1.6.4-alpha.0 版本已修复,可以试下

@Gamehu
Copy link
Author

Gamehu commented Aug 3, 2020

@Gamehu 1.6.4-alpha.0 版本已修复,可以试下

好的,谢谢

@Gamehu
Copy link
Author

Gamehu commented Aug 3, 2020

moduleNameMapper: {
		'^\\$ice/history$': './router/history'
	}

好的 我试下

@chenbin92
Copy link
Collaborator

moduleNameMapper: {
		'^\\$ice/history$': './router/history'
	}

好的 我试下

直接使用 icejs@1.6.4-alpha.0 版本即可,不需要配置 了

@Gamehu
Copy link
Author

Gamehu commented Aug 3, 2020

moduleNameMapper: {
		'^\\$ice/history$': './router/history'
	}

好的 我试下

直接使用 icejs@1.6.4-alpha.0 版本即可,不需要配置 了

OK,不过我看还是不能单独跑某个test,而是必须要用icejs test才行是吧?

另外我在咱们得build.json配置了请求的代理,测试用例里没有用到而是默认用的localhost,我应该怎么配置呢?

  "proxy": {
    "/api": {
      "enable": true,
      "target": "http://xxxx:8087"
    },

services的代码:


export default {
  async fetchList(params) {
    return await request.post('/api/v1/domain/getResourcesByDomainId', {
      ...params,
      id: mockId,
    });
  },
};

报错信息:

    Network Error

      at createError (node_modules/axios/lib/core/createError.js:16:15)
      at XMLHttpRequest.handleError (node_modules/axios/lib/adapters/xhr.js:83:14)
      at XMLHttpRequest.<anonymous> (node_modules/jsdom/lib/jsdom/living/helpers/create-event-accessor.js:33:32)
      at invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:193:27)
      at XMLHttpRequestEventTargetImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:119:9)
      at XMLHttpRequestEventTargetImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:82:17)
      at XMLHttpRequest.dispatchEvent (node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:157:21)
      at requestErrorSteps (node_modules/jsdom/lib/jsdom/living/xhr-utils.js:132:7)
      at Object.dispatchError (node_modules/jsdom/lib/jsdom/living/xhr-utils.js:62:3)
      at Request.<anonymous> (node_modules/jsdom/lib/jsdom/living/xmlhttprequest.js:676:20)
      at Request.onRequestError (node_modules/request/request.js:877:8)

  console.error node_modules/jsdom/lib/jsdom/virtual-console.js:29

@LanceZhu
Copy link
Collaborator

LanceZhu commented Aug 4, 2020

是必须要用 icejs test

@LanceZhu
Copy link
Collaborator

LanceZhu commented Aug 4, 2020

build.json 中配置的 proxy 是针对本地开发时启动的 webpack-dev-server的。
可以在 request#请求配置 中配置 baseUrl 指向对应域名。

@Gamehu
Copy link
Author

Gamehu commented Aug 4, 2020

build.json 中配置的 proxy 是针对本地开发时启动的 webpack-dev-server的。
可以在 request#请求配置 中配置 baseUrl 指向对应域名。

好的 ,我试下 感谢

@Gamehu
Copy link
Author

Gamehu commented Aug 4, 2020

是必须要用 icejs test

你好,测试services下的方法,因为需要验证权限,所以用如下方式携带cookie实现免验证,postman没问题,但是跑测试用例有问题,

测试用例:

test('listService fetchList', async () => {
		const params = { pageNum: 1, pageSize: 10 }
		const headers = {
			Cookie: 'JSESSIONID=NzI1N2FjYzEtY2Y1MC00MmNkLWIzODEtM2VmZTUzMzdkNDc2',
		}
		const config = {
			withCredentials: true,
			headers: { ...headers },
		}
		const data = await listService.fetchList(params, config)
		expect(data).not.toBeNull()
	})

源代码:

import { request } from "ice";
const id= "00000000-0d00-0000-0000-000000000000";

export default {
  async fetchList(params, config) {
    return await request.post(
      "/api/v1/domain/getResourcesByDomainId",
      {
        ...params,
        id,
      },
      { ...config }
    );
  },
};

报错信息:

携带cookie未生效,还是要求登录之后才能操作
```
Request failed with status code 401

  at createError (node_modules/axios/lib/core/createError.js:16:15)
  at settle (node_modules/axios/lib/core/settle.js:17:12)
  at XMLHttpRequest.handleLoad (node_modules/axios/lib/adapters/xhr.js:61:7)
  at XMLHttpRequest.<anonymous> (node_modules/jsdom/lib/jsdom/living/helpers/create-event-accessor.js:33:32)
  at invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:193:27)
  at XMLHttpRequestEventTargetImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:119:9)
  at XMLHttpRequestEventTargetImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:82:17)
  at XMLHttpRequest.dispatchEvent (node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:157:21)
  at readyStateChange (node_modules/jsdom/lib/jsdom/living/xmlhttprequest.js:811:9)
  at Request.<anonymous> (node_modules/jsdom/lib/jsdom/living/xmlhttprequest.js:939:7)
  at IncomingMessage.<anonymous> (node_modules/request/request.js:1076:12)

console.error .ice/request/request.ts:38
Error: Request failed with status code 401
...........

@LanceZhu
Copy link
Collaborator

LanceZhu commented Aug 5, 2020

request 是基于 axios 的,可以在 config 中 配置

{
+	withFullResponse: true
}

查看详细返回数据。

应该不是 icejs 的问题,可以单独用 axios 测试下请求,看下携带 cookie 是否正常。

@Gamehu
Copy link
Author

Gamehu commented Aug 5, 2020

withFullResponse: true

好的 谢谢

@Gamehu
Copy link
Author

Gamehu commented Aug 5, 2020

另外我想请问,怎么获取store中的数据呢,我用如下方式获取不到

import React from 'react'
import AlarmAnalyze from '../../../src/pages/ResourceCenter/index'
import ResourceList from '../../../src/pages/ResourceCenter/components/list'
import { store as pageStore } from 'ice/ResourceCenter'
import { shallow, mount } from 'enzyme'
import treeService from '../../../src/pages/ResourceCenter/services/tree'
const PageProvider = pageStore.Provider

const WithResourceListModel = (props) => {
	return (
		<PageProvider>
			<ResourceList {...props} />
		</PageProvider>
	)
}

const WithPageModel = (props) => {
	return (
		<PageProvider>
			<AlarmAnalyze {...props} />
		</PageProvider>
	)
}

let wrapper
beforeEach(() => {
	wrapper = shallow(<WithPageModel />)
})

describe('render', () => {
	test('Test Row  ', () => {
		const cwrapper = wrapper.find('Row')
		expect(cwrapper).not.toBeNull
		const Col = wrapper.find('Col')
		expect(Col).not.toBeNull
	})

	test('Test ResourceList  ', () => {
		const cwrapper = wrapper.find('ResourceList')
		const list = pageStore.useModel('list')
		expect(list).not.toBeNull
		expect(cwrapper.prop('data')).toEqual({ ciType: '', current: 1, keyword: '', list: [], pageSize: 10, total: 0 })
	})

报错

   Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:      
    1. You might have mismatching versions of React and the renderer (such as React DOM)
    2. You might be breaking the Rules of Hooks
    3. You might have more than one copy of React in the same app
    See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.

      39 |      test('Test ResourceList  ', () => {
      40 |              const cwrapper = wrapper.find('ResourceList')
    > 41 |              const list = pageStore.useModel('list')

@LanceZhu
Copy link
Collaborator

LanceZhu commented Aug 6, 2020

报错显示 pageStore.useState 应放到 React 函数组件中,可以在外面包装一个 React 函数组件。
而且 useState 应当这样用吧。

const [list] = useState('list')

@chenbin92
Copy link
Collaborator

已发布正式版本 icejs@1.7.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants