javascript - Can't successfully test a custom hook using useState and useEffect - Stack Overflow

While learning React, I'm trying to understand custom hooks.I've created a simple one updati

While learning React, I'm trying to understand custom hooks.

I've created a simple one updating an internal "step" on creation, cleanup, and allows for external updates.

But I'm struggling to successfully implements its unit tests on "step" update and cleanup. It's as if the the returned "step" value is not updated anymore after the hook creation.

How can fix the tests? Did I miss some key concepts?

Here is the custom hook:

const useCustomHook = (stepToSet: string) => {
  const [step, setStep, ] = useState('');

  useEffect(() => {
    if (stepToSet) {
      setStep(stepToSet);
    }

    return () => {
      setStep('cleanup');
    };
  }, [stepToSet, ]);

  const externalCb = (externalStepToSet: string) => {
    setStep(externalStepToSet);
  };

  return {
    step,
    externalCb,
  };
};

Jest unit test:

import {
  act, renderHook, 
} from '@testing-library/react-hooks';
import { expect, } from 'chai';

describe('useCustomHook Hook', () => {

  it('step updates test', async () => {

    const {
      result,
      unmount,
      waitFor,
    } = renderHook(() => {
      return useCustomHook('created');
    });

    const {
      step,
      externalCb,
    } = result.current;

    expect(step).to.be.equal('created');

    act(() => externalCb('updated'));
    await waitFor(() => {});
    expect(step).to.be.equal('updated');

    act(() => unmount());
    await waitFor(() => {});
    expect(step).to.be.equal('cleaned');
  });
});

The test keeps failing with the message:

assert.strictEqual(received, expected)

Expected value to strictly be equal to:
  "updated"
Received:
  "created"

Message:
  expected 'created' to equal 'updated'

Difference:

- Expected
+ Received

- updated
+ created
...

The test still fails with the same message if I remove async and the await lines.

While learning React, I'm trying to understand custom hooks.

I've created a simple one updating an internal "step" on creation, cleanup, and allows for external updates.

But I'm struggling to successfully implements its unit tests on "step" update and cleanup. It's as if the the returned "step" value is not updated anymore after the hook creation.

How can fix the tests? Did I miss some key concepts?

Here is the custom hook:

const useCustomHook = (stepToSet: string) => {
  const [step, setStep, ] = useState('');

  useEffect(() => {
    if (stepToSet) {
      setStep(stepToSet);
    }

    return () => {
      setStep('cleanup');
    };
  }, [stepToSet, ]);

  const externalCb = (externalStepToSet: string) => {
    setStep(externalStepToSet);
  };

  return {
    step,
    externalCb,
  };
};

Jest unit test:

import {
  act, renderHook, 
} from '@testing-library/react-hooks';
import { expect, } from 'chai';

describe('useCustomHook Hook', () => {

  it('step updates test', async () => {

    const {
      result,
      unmount,
      waitFor,
    } = renderHook(() => {
      return useCustomHook('created');
    });

    const {
      step,
      externalCb,
    } = result.current;

    expect(step).to.be.equal('created');

    act(() => externalCb('updated'));
    await waitFor(() => {});
    expect(step).to.be.equal('updated');

    act(() => unmount());
    await waitFor(() => {});
    expect(step).to.be.equal('cleaned');
  });
});

The test keeps failing with the message:

assert.strictEqual(received, expected)

Expected value to strictly be equal to:
  "updated"
Received:
  "created"

Message:
  expected 'created' to equal 'updated'

Difference:

- Expected
+ Received

- updated
+ created
...

The test still fails with the same message if I remove async and the await lines.

Share Improve this question edited Mar 13 at 19:54 Drew Reese 204k18 gold badges245 silver badges273 bronze badges asked Mar 13 at 17:09 DgurioDgurio 132 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 1

Issues

  • The result is holds a reference to the hook's current return value, but in your test you only access the initial value before effecting any changes, the later assertions don't have the updated hook value.
  • When a hook/component unmounts, any enqueued state updates are a non-operation. After unmounting no state updates will be processed.

Solution Suggestions

  • Update the test cases to access result.current each time after an act.
  • Remove any assertions after unmounting the hook.
  • The waitFor calls appear to be superfluous since they are empty and could/should probably be removed. AFAIK act is sufficient for triggering a re-render and hook update.
import { act, renderHook } from "@testing-library/react";
import { expect } from "chai";
import { useCustomHook } from "./useCustomHook";

describe("useCustomHook Hook", () => {
  it("step updates test", () => {
    const { result, unmount } = renderHook(useCustomHook, {
      initialProps: "created",
    });

    // Initial step value when mounted
    expect(result.current.step).to.be.equal("created");

    // Update state
    act(() => result.current.externalCb("updated"));
    expect(result.current.step).to.be.equal("updated");

    // Unmount
    act(() => unmount());
    // No update is expected here, I guess you could assert
    // nothing changed in the hook state
    expect(result.current.step).to.be.equal("updated");
  });
});

If you need to waitFor any updates though, the correct usage would be similar to the following:

import { act, renderHook, waitFor } from "@testing-library/react";
import { expect } from "chai";
import { useCustomHook } from "./useCustomHook";

describe("useCustomHook Hook", () => {
  it("step updates test", async () => {
    const { result, unmount } = renderHook(useCustomHook, {
      initialProps: "created",
    });

    expect(result.current.step).to.be.equal("created");

    act(() => result.current.externalCb("updated"));
    await waitFor(() => {
      expect(result.current.step).to.be.equal("updated");
    });

    act(() => unmount());
    await waitFor(() => {
      expect(result.current.step).to.be.equal("updated");
    });
  });
});

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744688530a4588065.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信