简体   繁体   中英

How to test with jest and vue-test-utils simulate upload file

I'm use jest with vue-test-utils and I want test method for upload files. This method in vue file component.

async uploadFiles(file){
  this.$refs.iconUpload.setAttribute('data-load', 'loading')
  let formData = new FormData();
  formData.append('image', file);

  try{
    const result = await fetch('/upload', {
      method: 'POST',
      body: formData,
    })
    const data = await result.json();
    if(data.status){
      this.$refs.iconUpload.setAttribute('data-load', 'success')
      this.$refs.btnClear.style.display = 'none';
      this.$refs.btnGoBack.style.display = 'none';
      this.uploadDone = true;
    }else {
      this.showSpecialError(this.$refs.elseError)
    }
  }catch (e){
    this.showSpecialError(this.$refs.elseError)
    return null
  }
}

and I want to test it with resolve and reject

const file = {
  size: 500,
  type: 'image/png',
  name: 'image.png
};

const event = {
  target: {
    files: [file],
  },
};

global.fetch = jest.fn(() => Promise.resolve({
  json: () => Promise.resolve({ data })
}));

test('the function of sending the file returns the required response on a successful response', async () => {
    const result = await wrapper.vm.uploadFiles(event)
    expect(result).toEqual(file)
})

But the test always returns null

在此处输入图像描述

In the test, you are awaiting the result of uploadFiles function. But uploadFiles does not return the file, as your test seems to expect.

It would, if, at the end of the try {} block, you'd add:

return data;

Because uploadFiles is async , the returned value would automatically be wrapped in a promise. So it would be equivalent with returning Promise.resolve(data) in a synchronous function.

But returning data at the end of the try{} block is not what you should do, really.

Inside your component method, the only thing you're checking from the response of the /upload call is whether or not a truthy status is set on the response ( if (data.status) ). Which is simply wrong, because a status of 404 (not found) is truthy. So is a status of 500 (server error). All server error statuses, in fact, are truthy, because they are all finite, positive numbers.

Getting back to the test, you have two options:

a)
if you want to test the current component code (which you shouldn't), all you need to test is if wrapper.vm.uploadDone gets set to true when fetch returns a response containing a truthy status value.

This test would pass with your current component:

global.fetch = jest.fn(() => Promise.resolve({
  json: () => Promise.resolve({ status: 404 })
}));

test('uploadDone gets set to true when receiving a truthy response from /upload', async () => {
   expect(wrapper.vm.uploadDone).toBe(false);
   await wrapper.vm.uploadFiles({
     size: 500,
     type: 'image/png',
     name: 'image.png'
   });
   expect(wrapper.vm.uploadDone).toBe(true);
})

But, in reality, your uploadFiles should not be setting uploadDone when receiving a result with a status other than 200 .

My advice to you is to go for the alternative:

b)
call for help from a senior on your team, who could explain in detail the above and would help rewrite the uploadFiles function. Until that method doesn't do what it should, there's not much point in writing tests for it.

Tests are there to make sure the app behaves as expected both when external systems fail and when they perform as expected.
My impression is that your app does not currently perform according to expectations.

So write the test according to the actual (client) expectations. And than write the code which passes all expectations.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM