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

如何在Vue测试中Mock第三方Window对象?解决createMidtransToken方法测试报错问题

How to Properly Test the createMidtransToken Method in Your Vue Component

The error you're seeing happens because your current way of defining window.MidtransNew3ds is incorrect—you're not properly setting up the object that contains the getCardToken mock function. Let's break down the fix and build out a complete test suite for this method.

Step 1: Fix the window.MidtransNew3ds Mock

Your original Object.defineProperty usage is misconfigured. Instead, directly assign a mock object to window.MidtransNew3ds before your tests, and clean it up afterward to avoid cross-test contamination.

// In your CheckoutButton.spec.js
import { shallowMount } from '@vue/test-utils';
import CheckoutButton from '@/components/CheckoutButton.vue';

describe('CheckoutButton', () => {
  let wrapper;

  beforeEach(() => {
    // Initialize the mock MidtransNew3ds object before each test
    window.MidtransNew3ds = {
      getCardToken: jest.fn()
    };

    // Mount the component with necessary mocks
    wrapper = shallowMount(CheckoutButton, {
      global: {
        mocks: {
          $store: {
            state: {
              payment: {
                creditCardPayload: { 
                  number: '4111111111111111',
                  expiry_month: '12',
                  expiry_year: '2025'
                }
              }
            }
          },
          $alertModal: {
            show: jest.fn()
          }
        },
        data() {
          return {
            paymentTypeChoosen: { 
              type: 'credit_card'
            }
          };
        },
        methods: {
          payCheckout: jest.fn(),
          handleRouteError: jest.fn()
        }
      }
    });
  });

  afterEach(() => {
    // Clean up the mock after each test
    delete window.MidtransNew3ds;
    jest.clearAllMocks();
    wrapper.unmount();
  });

  // Your initial test, now working
  it('Should call MidtransNew3ds.getCardToken when createMidtransToken runs', () => {
    wrapper.vm.createMidtransToken();
    expect(window.MidtransNew3ds.getCardToken).toHaveBeenCalled();
    // Optional: Verify it's called with the correct parameters
    expect(window.MidtransNew3ds.getCardToken).toHaveBeenCalledWith(
      wrapper.vm.$store.state.payment.creditCardPayload,
      expect.objectContaining({
        onSuccess: expect.any(Function),
        onFailure: expect.any(Function)
      })
    );
  });
});

Step 2: Test Success and Failure Scenarios

To make your tests comprehensive, verify that the callback functions work as expected:

Test Success Callback

it('Should trigger payCheckout with the correct payload on token success', () => {
  const mockTokenId = 'midtrans-token-12345';
  
  // Mock getCardToken to trigger the onSuccess callback
  window.MidtransNew3ds.getCardToken.mockImplementation((card, options) => {
    options.onSuccess({ token_id: mockTokenId });
  });

  wrapper.vm.createMidtransToken();

  expect(wrapper.vm.payCheckout).toHaveBeenCalledWith({
    ...wrapper.vm.paymentTypeChoosen,
    token: mockTokenId
  });
});

Test Failure Callback

it('Should show error alert when token creation fails', () => {
  const mockErrorMessage = 'Invalid card details';
  
  // Mock getCardToken to trigger the onFailure callback
  window.MidtransNew3ds.getCardToken.mockImplementation((card, options) => {
    options.onFailure({ status_message: mockErrorMessage });
  });

  wrapper.vm.createMidtransToken();

  expect(wrapper.vm.$alertModal.show).toHaveBeenCalledWith(expect.objectContaining({
    type: 'error',
    title: 'Transaksi Dibatalkan',
    text: mockErrorMessage,
    buttonEvent: expect.any(Function)
  }));

  // Optional: Test the button event triggers handleRouteError
  const alertOptions = wrapper.vm.$alertModal.show.mock.calls[0][0];
  alertOptions.buttonEvent();
  expect(wrapper.vm.handleRouteError).toHaveBeenCalled();
});

Why Your Original Code Failed

Your original Object.defineProperty call tried to set getCardToken as a property of window.MidtransNew3ds, but you never actually created the MidtransNew3ds object itself. By directly assigning window.MidtransNew3ds = { getCardToken: jest.fn() }, you properly define the object and its mock method.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 06:49:16