开玩笑 +反应组件
#react #node #tdd #jest

测试驱动的开发

如果您是TDD或Jest的新手,请查看本文末尾的资源部分。

代码

我有一个反应组件,SiteBreadcrumbs.tsx,它使用BreadcrumbsHelper类生成站点面包屑。

sitebreadcrumbs.tsx

import BreadcrumbsHelper from '../../../../utils/BreadcrumbsHelper';
import { BreadcrumbDataProvider } from '../../../../dal/BreadcrumbDataProvider';
import { PageContextDataProvider } from '../../../../dal/PageContextDataProvider';

React.useEffect(() => {
    //...
    const helper = new BreadcrumbsHelper(dataProvider, pageContextProvider);

    helper.getBreadcrumbs()
        .then((result) => {
             setLinkItems(result);
         })
         .catch((error) => {
             console.log(error);
          });
}, []);

breadcrumbshel​​per.ts

export default class BreadcrumbsHelper {

constructor(protected dataProvider: BreadcrumbDataProvider, protected pageContextProvider: PageContextDataProvider) {}

    public getBreadcrumbs = async (): Promise<IBreadcrumbItem[]> => {
        const items: IBreadcrumbItem[] = [];
        //...
        return items;
    }
    //...
}

测试

不是很好的方法

jest允许mocking partials,因此我可以使用以下代码模拟BreadcrumbsHelper.getBreadcrumbs()方法:

sitebreadcrumbs.test.tsx
jest.mock('../../src/utils/BreadcrumbsHelper', () => {
    const originalModule = jest.requireActual('../../src/utils/BreadcrumbsHelper');
    return {
        __esModule: true, //<- required for ES modules
        ...originalModule,
        default: jest.fn().mockImplementation(() => {
            return {
                getBreadcrumbs: jest.fn().mockImplementation(() => {
                    return Promise.resolve([];
                })
            };
        }),
    };
});

但是,在我的测试中,我想介绍不同的情况:网站的欢迎页面,网站(其他)页面,subsite等。我当然不会创建单独的文件来覆盖它们。

正确的方法

您会发现许多有关如何模拟功能的示例,但是这里复杂的部分是getBreadcrumbs是一种类方法,并且不作为函数导出。

jest要求jest.mock('../../src/utils/BreadcrumbsHelper')在测试之上,但是我可以使用每个测试更改getBreadcrumbs模拟。

(BreadcrumbsHelper as jest.Mock).mockReturnValueOnce({
    getBreadcrumbs: jest.fn().mockResolvedValue(BreadcrumbsConfig.TeamSiteWelcomePage)
})
sitebreadcrumbs.test.tsx
import BreadcrumbsHelper from '../../src/utils/BreadcrumbsHelper';
jest.mock('../../src/utils/BreadcrumbsHelper')

const BreadcrumbsConfig = {
    TeamSiteWelcomePage: [
        { "text": "Intranet", "key": "1", "href": "https://contoso.sharepoint.com/sites/Intranet"}
    ],
    TeamSiteInsightsPage: [
        { "text": "Intranet", "key": "1", "href": "https://contoso.sharepoint.com/sites/Intranet"},
        { "text": "Insights", "key": "2", "href": ""}
    ],
    //...
}

describe('SiteBreadcrumbs', () => {
    it('should render breadcrumbs on TeamSite WelcomePage', async () => {
        (BreadcrumbsHelper as jest.Mock).mockReturnValueOnce({
            getBreadcrumbs: jest.fn().mockResolvedValue(BreadcrumbsConfig.TeamSiteWelcomePage)
        })
        await act(async () => {
            siteBreadcrumbs = render(<SiteBreadcrumbs pageContext={mockPageContext} spfiContext={mockSPFI} />);
        });
        //...
    });

    it('should render breadcrumbs on TeamSite InsightsPage', async () => {
        (BreadcrumbsHelper as jest.Mock).mockReturnValueOnce({
            getBreadcrumbs: jest.fn().mockResolvedValue(BreadcrumbsConfig.TeamSiteInsightsPage)
        })

        await act(async () => {
            siteBreadcrumbs = render(<SiteBreadcrumbs pageContext={mockPageContext} spfiContext={mockSPFI} />);
        });
        //...
    });
}

资源