1
votes

I'm using mongodb-memory-server package and am having some trouble getting my async jest tests to run properly. I have a beforeAll that connects to a memory mongo database:

beforeAll(async () => await connect());

then I have an async test:

it("creates a new user", async () => {
      const userObj = {
        firstName: faker.name.firstName(),
        lastName: faker.name.lastName(),
        phoneNumber: "+14444444444",
        uid: faker.random.uuid(),
      };
      const userRes = await axios.post(routeUrl + "/", userObj);
      const createdUser = userRes.data.user;
      expect(createdUser._id).toBeTruthy();
  });

the issue is that my test always times out when it is both async and includes an endpoint that modifies some data using the mongodb-memory-server. If I were to remove the async and put the logic after userRes in a .then, the test passes. If I keep the async/await but wrap the code inside the test in a 1000ms async timeout, the test passes. Any thoughts on why the test is timing out in this current format shown above?

Here is an example of a passing version of the test:

it("creates a new user", () => {
      const userObj = {
        firstName: faker.name.firstName(),
        lastName: faker.name.lastName(),
        phoneNumber: "+14444444444",
        uid: faker.random.uuid(),
      };
      axios.post(routeUrl + "/", userObj).then(
         userRes => {
             const createdUser = userRes.data.user;
             expect(createdUser._id).toBeTruthy();
         }
      );
  });
2
Can you share the passing version? It may be that your version with the .then isn't returning the promise and so jest isn't waiting for it to "pass the test". You can also confirm the checks run by adding a jestjs.io/docs/en/expect#expectassertionsnumber check.dcwither
@dcwither just added an example of a passing testAndy Lebowitz
Why aren't you mocking the mongodb stuff with jest.mock and use something like for the application router testing with something like npmjs.com/package/supertest?Max
My interpretation was that this is an end to end/integration test, and so I didn't comment on that, but if this is intended to be a unit test, then Max's question points to some valuable resources.dcwither

2 Answers

2
votes

It looks like your passing .then test isn't actually finishing. In the async test, the await ensures that the promise finishes before the async function resolves.

In your passing .then test, it's actually not running the check before the test "passes". In order to fix this, and get an accurate test, you could make the following changes:

it("creates a new user", () => {
  expect.assertions(1);
  const userObj = {
    firstName: faker.name.firstName(),
    lastName: faker.name.lastName(),
    phoneNumber: "+14444444444",
    uid: faker.random.uuid(),
  };
  return axios.post(routeUrl + "/", userObj).then((userRes) => {
    const createdUser = userRes.data.user;
    expect(createdUser._id).toBeTruthy();
  });
});

You should find that this times out as well.

This change (adding the return and the expect.assertions) ensures that the promise resolves before the test finishes. You can look at Jest's async example for more details on how this works.

Using expect.assertions(number) is really useful to ensure async tests are actually testing what you intend to test.

In order to resolve the timeout (if the issue is that 1000ms is too little), you can set the timeout explicitly using the 3rd argument to it/test.

it("creates a new user", () => {...}, 2000)
-1
votes