Vue with jest - 使用异步调用进行测试

Posted

技术标签:

【中文标题】Vue with jest - 使用异步调用进行测试【英文标题】:Vue with jest - Test with asynchronous call 【发布时间】:2019-01-19 14:40:00 【问题描述】:

如何让我的测试等待我的 api 的结果? 我正在使用 vue 和 jest 来测试我的组件。

我想测试将客户端写入我的数据库的方法。在我的组件中,我有以下方法:

methods: 

  onSubmitClient()

   axios.post(`urlApi`, this.dados).then(res => 

      return res;
   )

  

在我的测试中

describe('login.vue', () => 

  let wrapper

  beforeAll(()=>

    wrapper = mount(client, 
      stubs: ['router-link'],
      store,
      data() 
          return 
              dados: 
                  name: 'tes name',
                  city: 'test city'
              ,
          ;
      
    )
  )

  it('store client', () => 

    res = wrapper.vm.onSubmitLogin()
    console.log(res);

  )

)

我的测试不等待 API 调用完成。我需要等待 API 调用才能知道测试是否有效。如何让我的测试等待 API 返回?

【问题讨论】:

等待API调用是什么意思?您是否在单元测试中提出实际请求? 是的。我提出了真正的要求。我想知道我的组件是否将数据保存在我的 api 中。 不是一个单元测试,你应该为此排除客户端。如果您想针对真实后端测试真实请求,请在更高级别使用 E2E 测试。 @jonrsharpe 但你也需要一个测试框架:)。你会在某个时候、某个地方遇到这个问题。通过轮询、订阅事件或代理实际请求来检查正在发出的请求......这是一个有效的问题。 我使用 e2e nightwatchjs 开始了测试。只有我无法执行测试,因为 nightwatchjs 无法从 element.io 中选择一个选项。 element.io 的 select 是 ul li 所以不能选择。我决定用 jest 来测试,但这也很难。 【参考方案1】:

您的代码中有几个问题。

首先,你不能returnfrom an async call。相反,您可能应该在 onSubmitClient 中设置一些数据,并返回整个 axioscall,这是一个 Promise。例如:

onSubmitClient()
  return axios.post(`urlApi`, this.dados).then(res => 
      this.result = res;
      return res;
  )

我假设这里的方法是从服务器存储result。也许你不想要那个;这只是一个例子。我稍后会回来。

好的,现在,您可以在包装器中调用onSubmitClient 并查看this.result 是否已设置。如您所知,这并不简单。

为了让笑话测试等待异步代码,you need either to provide a done callback function or return a promise。我将展示一个与前者的例子:

it('store client', (done) => 
  wrapper.vm.onSubmitLogin().then((res) => 
    expect(wrapper.vm.dados).toEqual(res);
    done();
  )
);

现在这段代码应该可以正常工作,但正如@jonsharpe 在评论中所说,它仍然存在问题。

您通常不希望在单一测试中执行真实网络请求,因为它们速度慢且不可靠。此外,单一测试旨在单独测试组件,在这里我们不仅要测试我们的组件在发出请求时正确设置 this.result。我们也在测试是否有一个正在运行的网络服务器。

因此,在这种情况下,我要测试单个功能,将请求提取到另一个方法,用vue-test-utilsjest.fn 模拟它,然后断言onSubmitClient 完成它的工作:

组件:

export default 
  data() 
    return 
      http: axios,
      ...
    ,
    methods: 

      onSubmitClient()
        this.http.post(`urlApi`, this.dados).then(res => 
            this.result = res;
        )
      
    
  

测试:

it('store client', (done) => 
  const fakeResponse = foo: 'bar';
  var post = jest.fn();
  var http : 
    post,
  ;
  var wrapper = mount(client, 
    stubs: ['router-link'],
    store,
    data() 
      return 
        dados: 
            name: 'tes name',
            city: 'test city'
        ,
        http, //now, the component under test will user a mock to perform the http post request.
      
      
  );
  wrapper.vm.onSubmitLogin().then( () => 
    expect(post).toHaveBeenCalled();
    expect(wrapper.vm.result).toEqual(fakeResponse);
    done();
  )

);

现在,您的测试断言了两件事:

    post 被调用。 this.result 已按应有的方式设置。

如果您不想在您的组件中存储任何来自服务器的内容,只需在方法中删除第二个断言和 this.result = res 行。

所以基本上这涵盖了为什么您的测试不等待异步请求以及代码中的一些问题。还有一些事情需要考虑(我认为全局wrapper 是个坏主意,在测试组件行为时我总是更喜欢shallowMount 而不是mount),但这个答案应该对你有很大帮助。

PS:没有测试代码,所以也许我搞砸了。如果事情不起作用,请查找语法错误或类似问题。

【讨论】:

感谢@Sergeon,可爱的回答并向雷纳托展示了前进的好方法。我想问更多问题不会让他走上这条路。

以上是关于Vue with jest - 使用异步调用进行测试的主要内容,如果未能解决你的问题,请参考以下文章

使用 Node 进行 Jest 测试 - 超时 - 在 jest.setTimeout 指定的 5000 毫秒超时内未调用异步回调

Got Timeout - 在 jest.setTimeout 指定的 5000 毫秒超时内未调用异步回调

Vue JS with story hot config for storybook and jest error in Cannot find module '@storybook/vue/dist

JEST @vue/composition-api + Jest 测试套件无法运行 [vue-composition-api] 在使用任何函数之前必须调用 Vue.use(VueComposition

超时 - 在 jest.setTimeout 指定的 5000 毫秒超时内未调用异步回调

在 Nuxt、Vue、jest 和 Vuetify 中为项目编写单元测试