2016-09-12 105 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