2016-09-12 107 views
1

我对我的组件之一使用了jest快照测试,并且生成的snap文件很大(199Kb和4310行)。当快照测试失败时,所有的快照文件都会打印到控制台(即3-4秒的渲染),它给了我这个“你做错了什么”的感觉。Jest快照测试

所以我的问题是:我使用正确的快照测试?

组件代码:

import _ = require('lodash'); 
import React = require('react'); 
import {TranslatedMessage} from 'translator'; 

import {UserProfile} from './user-profile'; 
import {ICustomerProfile} from '../customer/customer-profile'; 

interface IUserProfile { 
    firstName: string; 
    lastName: string; 
    id: string; 
    customer: ICustomerProfile; 
    job: string; 
    email: string; 
    contacts: string; 
    phoneNumber: string; 
} 

interface IUserProfileProps { 
    contact: IUserProfile; 
} 

interface IUserProfileState {} 

export class UserProfile extends React.Component<IUserProfileProps, IUserProfileState> { 
    constructor(props: IUserProfileProps) { 
     super(props); 
    } 

    public render(): JSX.Element { 
     return (
      <div className="ext-admin-user-infos-details"> 
       <div className="ext-admin-user-infos-details-content"> 
        <div className="row"> 
         <div className="col-md-12"> 
          <h3>{this.props.contact.firstName } {this.props.contact.lastName}</h3> 
          <p className="ext-subtitle"> 
           <span className="ext-minor">{this.props.contact.id}</span> 
          </p> 
         </div> 
        </div> 
        <div className="row"> 
         <div className="col-md-8"> 
          <div className="ext-admin-user-infos-card"> 
           <h6> 
            <TranslatedMessage messageKey="common.labels.customer" /> 
           </h6> 
           <ul> 
            <li>{this.props.contact.customer.name}</li> 
           </ul> 
          </div> 
          <div className="ext-admin-user-infos-card"> 
           <h6> 
            <TranslatedMessage messageKey="admin.contact.infos.job" /> 
           </h6> 
           <ul> 
            <li>{this.props.contact.job}</li> 
           </ul> 
          </div> 
          <div className="ext-admin-user-infos-card"> 
           <h6> 
            <TranslatedMessage messageKey="admin.contact.infos.email" /> 
           </h6> 
           <ul> 
            <li>{this.props.contact.email}</li> 
           </ul> 
          </div> 
         </div> 
         <div className="col-md-4"> 
          <div className="ext-admin-user-infos-card"> 
           <h6> 
            <TranslatedMessage messageKey="common.labels.followed" /> 
           </h6> 
           <ol> 
            {this.renderContacts(this.props.contact.contacts)} 
           </ol> 
          </div> 
          <div className="ext-admin-user-infos-card"> 
           <h6> 
            <TranslatedMessage messageKey="common.labels.phone" /> 
           </h6> 
           <ul> 
            <li>{this.props.contact.phoneNumber}</li> 
           </ul> 
          </div> 
         </div> 
        </div> 
       </div> 
      </div> 
     ); 
    } 

    protected renderContacts(contacts: IUserProfile[]): JSX.Element[] { 
     let contacts= []; 
     if (sales) { 
      _.map(sales, function(contact: IUserProfile): void { 
       salesContact.push(
        <li> 
         { contact.firstName} 
         { contact.lastName} 
        </li> 
       ); 
      }); 
     } 

     return contacts; 
    } 
} 

而且测试文件

jest.mock('TranslatedMessage'); 

import React = require('react'); 
import {render} from 'enzyme'; 

import {user} from '../../../tests/tools'; 

import {UserProfile} from '../../../app/components/user-profile/user-profile'; 

describe('UserProfile',() => { 
    it('should match the snapshot',() => { 
     const tree = render(<UserProfile user={user} />); 

     expect(tree).toMatchSnapshot(); 
    }); 
}); 

回答

1

信任的感觉。

您正在正确使用快照测试,但您已达到需要将大型组件分解为更小组件的程度。将它们分开将允许您嘲笑子组件,这将减少快照大小(每个快照,而不是汇总),并使您的差异更容易查看和修复。

代替

例如:

export class UserProfile extends Component { 
    public render() { 
    return (
     <div className="ext-admin-user-infos-details"> 
     <div className="ext-admin-user-infos-details-content"> 
      <div className="row"> 
      <div className="col-md-12"> 
       <h3>{this.props.contact.firstName } {this.props.contact.lastName}</h3> 
       <p className="ext-subtitle"> 
       <span className="ext-minor">{this.props.contact.id}</span> 
       </p> 
      </div> 
      </div> 
      // ... 
     </div> 
     </div> 
    ) 
    } 
} 

你这样做:

export class UserProfile extends Component { 
    public render() { 
    return (
     <div className="ext-admin-user-infos-details"> 
     <div className="ext-admin-user-infos-details-content"> 
      <div className="row"> 
      <div className="col-md-12"> 
       <UserProfileName 
       first={this.props.contact.firstName} 
       last={this.props.contact.firstName} 
       contactId={this.props.contact.id} 
       /> 
      </div> 
      </div> 
      // ... 
     </div> 
     </div> 
    ) 
    } 
} 

export class UserProfileName extends Component { 
    public render() { 
    return (
     <div> 
     <h3>{this.props.contact.first} {this.props.contact.last}</h3> 
     <p className="ext-subtitle"> 
      <span className="ext-minor">{this.props.contact.contactId}</span> 
     </p> 
     </div> 
    ); 
    } 
} 

请注意,我已经搬到逻辑呈现用户的姓名给另一个组件。下面是更新后的测试,嘲讽子组件:

jest.mock('TranslatedMessage'); 
jest.mock('UserProfileName'); // Mock this and other children 

import React = require('react'); 
import {render} from 'enzyme'; 

import {user} from '../../../tests/tools'; 

import {UserProfile} from '../../../app/components/user-profile/user-profile'; 

describe('UserProfile',() => { 
    it('should match the snapshot',() => { 
    const tree = render(<UserProfile user={user} />); 

    expect(tree).toMatchSnapshot(); 
    }); 
}); 

的快照,这将是比如果这一切都在一个组件小得多。当然,您也可以测试儿童组件:

import React = require('react'); 
import {render} from 'enzyme'; 

import {UserProfileName} from '../../../app/components/user-profile/user-profile-name'; 

describe('UserProfileName',() => { 
    it('should match the snapshot with all props',() => { 
    const tree = render(<UserProfile first="Test" last="Testerson" contactId="test-id" />); 

    expect(tree).toMatchSnapshot(); 
    }); 

    it('should render without a first name',() => { 
    const tree = render(<UserProfile last="Testerson" contactId="test-id" />); 

    expect(tree).toMatchSnapshot(); 
    }); 

    it('should render without a last name',() => { 
    const tree = render(<UserProfile first="Test" contactId="test-id" />); 

    expect(tree).toMatchSnapshot(); 
    }); 
}); 

请注意,在这些测试中,我在最后增加了两个案例。当你像这样分解组件时,理解和测试子组件的特定用例要容易得多!

最后,这种方法的一个额外的好处是,现在你有一个知道如何渲染用户名的可重用组件!你可以概括这一点,并随时随地把它放进去。

+0

谢谢主席先生:) – sanghin

-1

如果您使用enzyme,你应该用一个浅浅的渲染。

import { shallow } from 'enzyme'; 

const component = shallow(<UserProfile user={user} />); 

expect(component.text()).toMatchSnapshot(); 

您还可以使用react-test-renderer还有:

import renderer from 'react-test-renderer'; 

const component = renderer.create(<UserProfile user={user} />); 

const tree = component.toJSON(); 

expect(tree).toMatchSnapshot(); 
+0

随着您的解决方案快照只包含与像模拟用户值的对象: {} [email protected] 但感谢您抽出宝贵的时间来做出回复:) – sanghin