You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Jest测试包含两个纯组件的ImageBanner组件

Testing the ImageBanner Component with Jest and React Testing Library

Great question! When testing a component that conditionally renders child components based on props, we want to cover all possible scenarios: rendering only mobile, only desktop, both, or neither. Here's a step-by-step guide to writing comprehensive Jest tests for your ImageBanner component.

Prerequisites

Make sure you have these packages installed (if not already):

npm install --save-dev jest @testing-library/react @testing-library/jest-dom

Test Setup

First, let's assume your ImageBanner component is defined like this (based on your example):

// ImageBanner.jsx
import MobileBanner from './MobileBanner';
import DesktopBanner from './DesktopBanner';

export default function ImageBanner({ mobile, desktop }) {
  return (
    <div className="image-banner-container">
      {mobile?.image && <MobileBanner mobile={mobile} />}
      {desktop?.image && <DesktopBanner desktop={desktop} />}
    </div>
  );
}

We'll mock the MobileBanner and DesktopBanner components in our tests to focus on how ImageBanner behaves, rather than testing the child components themselves (you can write separate tests for those pure components if needed).

Test Cases

Create a test file ImageBanner.test.jsx with the following tests:

import React from 'react';
import { render, screen } from '@testing-library/react';
import ImageBanner from './ImageBanner';

// Mock the child components with test IDs for easy querying
jest.mock('./MobileBanner', () => ({ mobile }) => (
  <div data-testid="mobile-banner" src={mobile.image} alt={mobile.alt} />
));

jest.mock('./DesktopBanner', () => ({ desktop }) => (
  <div data-testid="desktop-banner" src={desktop.image} alt={desktop.alt} />
));

describe('ImageBanner Component', () => {
  // Reusable test data
  const mockMobileData = {
    image: 'mobile-banner.jpg',
    alt: 'Mobile promotional banner'
  };

  const mockDesktopData = {
    image: 'desktop-banner.jpg',
    alt: 'Desktop promotional banner'
  };

  it('renders only MobileBanner when mobile prop has image data', () => {
    render(<ImageBanner mobile={mockMobileData} desktop={{}} />);
    
    // Verify MobileBanner exists
    expect(screen.getByTestId('mobile-banner')).toBeInTheDocument();
    // Verify DesktopBanner does NOT exist
    expect(screen.queryByTestId('desktop-banner')).not.toBeInTheDocument();
  });

  it('renders only DesktopBanner when desktop prop has image data', () => {
    render(<ImageBanner mobile={{}} desktop={mockDesktopData} />);
    
    expect(screen.getByTestId('desktop-banner')).toBeInTheDocument();
    expect(screen.queryByTestId('mobile-banner')).not.toBeInTheDocument();
  });

  it('renders both banners when both props have image data', () => {
    render(<ImageBanner mobile={mockMobileData} desktop={mockDesktopData} />);
    
    expect(screen.getByTestId('mobile-banner')).toBeInTheDocument();
    expect(screen.getByTestId('desktop-banner')).toBeInTheDocument();
  });

  it('renders nothing when neither prop has image data', () => {
    const { container } = render(<ImageBanner mobile={{}} desktop={{}} />);
    
    // Check the wrapper div has no child elements
    expect(container.firstChild.children).toHaveLength(0);
  });

  it('passes correct props to MobileBanner when rendered', () => {
    render(<ImageBanner mobile={mockMobileData} />);
    
    const mobileBanner = screen.getByTestId('mobile-banner');
    expect(mobileBanner).toHaveAttribute('src', mockMobileData.image);
    expect(mobileBanner).toHaveAttribute('alt', mockMobileData.alt);
  });

  it('passes correct props to DesktopBanner when rendered', () => {
    render(<ImageBanner desktop={mockDesktopData} />);
    
    const desktopBanner = screen.getByTestId('desktop-banner');
    expect(desktopBanner).toHaveAttribute('src', mockDesktopData.image);
    expect(desktopBanner).toHaveAttribute('alt', mockDesktopData.alt);
  });
});

Key Explanations

  • Mocking Child Components: We use jest.mock to replace the actual banner components with simple mocks that include data-testid attributes. This lets us isolate the ImageBanner logic without worrying about the child components' internal HTML.
  • Query Methods: getByTestId is used when we expect an element to exist (it throws an error if not found), while queryByTestId is used when we expect an element to NOT exist (it returns null instead of throwing).
  • Prop Validation: We verify that the correct props are passed down to the child components, ensuring data flows as expected.

Alternative: Testing Without Mocking

If you prefer to test against the actual rendered HTML of your pure banner components, skip mocking and check for elements specific to those components. For example, if MobileBanner renders an <img> tag:

it('renders MobileBanner with correct image', () => {
  render(<ImageBanner mobile={mockMobileData} />);
  
  expect(screen.getByAltText('Mobile promotional banner')).toHaveAttribute('src', 'mobile-banner.jpg');
});

This approach validates the full component tree but is less focused on isolating ImageBanner's conditional logic.

内容的提问来源于stack exchange,提问作者RRP

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:07:02