开玩笑说:无法读取未定义的属性“天气”,不知道天气是什么

时间:2019-11-19 19:54:35

标签: javascript vue.js jestjs vuex vue-test-utils

我正在尝试对vuex getter进行测试,但是这给了我无法读取未定义的属性天气的信息,我无法理解“天气”是什么,我在此处仍未声明任何天气变量的地方仍然不知道开玩笑指的是天气。请帮我弄清楚。这是引发我的错误。如果需要,我可以提供更多代码

> weather-app@0.1.0 test C:\Users\guest1\Projects\Vue Cli\wheather-app
> jest

 PASS  src/test/navbar_test/navbar.test.js (27.728s)
 PASS  src/test/app_test/App.test.js (34.842s)
 FAIL  src/test/weather_test/weatherTemp.test.js (35.418s)
  ● Console

    console.error node_modules/vue/dist/vue.runtime.common.dev.js:621
      [Vue warn]: Error in render: "TypeError: Cannot read property 'weather' of undefined"

      found in

      ---> <Anonymous>
             <Root>
    console.error node_modules/vue/dist/vue.runtime.common.dev.js:1884
      TypeError: Cannot read property 'weather' of undefined
          at Proxy.render (C:\Users\guest1\Projects\Vue Cli\wheather-app\src\components\weather\weatherTemp.vue:29:357)
          at VueComponent.Vue._render (C:\Users\guest1\Projects\Vue Cli\wheather-app\node_modules\vue\dist\vue.runtime.common.dev.js:3532:22)
          at VueComponent.updateComponent (C:\Users\guest1\Projects\Vue Cli\wheather-app\node_modules\vue\dist\vue.runtime.common.dev.js:4048:21)
          at Watcher.get (C:\Users\guest1\Projects\Vue Cli\wheather-app\node_modules\vue\dist\vue.runtime.common.dev.js:4459:25)
          at new Watcher (C:\Users\guest1\Projects\Vue Cli\wheather-app\node_modules\vue\dist\vue.runtime.common.dev.js:4448:12)
          at mountComponent (C:\Users\guest1\Projects\Vue Cli\wheather-app\node_modules\vue\dist\vue.runtime.common.dev.js:4055:3)
          at VueComponent.Object.<anonymous>.Vue.$mount (C:\Users\guest1\Projects\Vue Cli\wheather-app\node_modules\vue\dist\vue.runtime.common.dev.js:8386:10)
          at init (C:\Users\guest1\Projects\Vue Cli\wheather-app\node_modules\vue\dist\vue.runtime.common.dev.js:3112:13)
          at createComponent (C:\Users\guest1\Projects\Vue Cli\wheather-app\node_modules\vue\dist\vue.runtime.common.dev.js:5952:9)
          at createElm (C:\Users\guest1\Projects\Vue Cli\wheather-app\node_modules\vue\dist\vue.runtime.common.dev.js:5899:9)
          at VueComponent.patch [as __patch__] (C:\Users\guest1\Projects\Vue Cli\wheather-app\node_modules\vue\dist\vue.runtime.common.dev.js:6449:7)
          at VueComponent.Vue._update (C:\Users\guest1\Projects\Vue Cli\wheather-app\node_modules\vue\dist\vue.runtime.common.dev.js:3927:19)
          at VueComponent.updateComponent (C:\Users\guest1\Projects\Vue Cli\wheather-app\node_modules\vue\dist\vue.runtime.common.dev.js:4048:10)
          at Watcher.get (C:\Users\guest1\Projects\Vue Cli\wheather-app\node_modules\vue\dist\vue.runtime.common.dev.js:4459:25)
          at new Watcher (C:\Users\guest1\Projects\Vue Cli\wheather-app\node_modules\vue\dist\vue.runtime.common.dev.js:4448:12)
          at mountComponent (C:\Users\guest1\Projects\Vue Cli\wheather-app\node_modules\vue\dist\vue.runtime.common.dev.js:4055:3)
          at VueComponent.Object.<anonymous>.Vue.$mount (C:\Users\guest1\Projects\Vue Cli\wheather-app\node_modules\vue\dist\vue.runtime.common.dev.js:8386:10)
          at mount (C:\Users\guest1\Projects\Vue Cli\wheather-app\node_modules\@vue\test-utils\dist\vue-test-utils.js:8649:21)
          at shallowMount (C:\Users\guest1\Projects\Vue Cli\wheather-app\node_modules\@vue\test-utils\dist\vue-test-utils.js:8677:10)
          at Object.it (C:\Users\guest1\Projects\Vue Cli\wheather-app\src\test\weather_test\weatherTemp.test.js:24:21)
          at Object.asyncJestTest (C:\Users\guest1\Projects\Vue Cli\wheather-app\node_modules\jest-jasmine2\build\jasmineAsyncInstall.js:102:37)
          at resolve (C:\Users\guest1\Projects\Vue Cli\wheather-app\node_modules\jest-jasmine2\build\queueRunner.js:43:12)
          at new Promise (<anonymous>)
          at mapper (C:\Users\guest1\Projects\Vue Cli\wheather-app\node_modules\jest-jasmine2\build\queueRunner.js:26:19)
          at promise.then (C:\Users\guest1\Projects\Vue Cli\wheather-app\node_modules\jest-jasmine2\build\queueRunner.js:73:41)
          at process._tickCallback (internal/process/next_tick.js:68:7)

  ● Getters.vue › Renders "store.getters.clicks" in h1

    TypeError: Cannot read property 'weather' of undefined

      27 |   align-items: flex-end;
      28 |   width: 100%;
    > 29 |   height: auto;
         |                                    ^
      30 | }
      31 |
      32 | .weather-quote {

      at Proxy.render (src/components/weather/weatherTemp.vue:29:357)
      at VueComponent.Vue._render (node_modules/vue/dist/vue.runtime.common.dev.js:3532:22)
      at VueComponent.updateComponent (node_modules/vue/dist/vue.runtime.common.dev.js:4048:21)
      at Watcher.get (node_modules/vue/dist/vue.runtime.common.dev.js:4459:25)
      at new Watcher (node_modules/vue/dist/vue.runtime.common.dev.js:4448:12)
      at mountComponent (node_modules/vue/dist/vue.runtime.common.dev.js:4055:3)
      at VueComponent.Object.<anonymous>.Vue.$mount (node_modules/vue/dist/vue.runtime.common.dev.js:8386:10)
      at init (node_modules/vue/dist/vue.runtime.common.dev.js:3112:13)
      at createComponent (node_modules/vue/dist/vue.runtime.common.dev.js:5952:9)
      at createElm (node_modules/vue/dist/vue.runtime.common.dev.js:5899:9)
      at VueComponent.patch [as __patch__] (node_modules/vue/dist/vue.runtime.common.dev.js:6449:7)
      at VueComponent.Vue._update (node_modules/vue/dist/vue.runtime.common.dev.js:3927:19)
      at VueComponent.updateComponent (node_modules/vue/dist/vue.runtime.common.dev.js:4048:10)
      at Watcher.get (node_modules/vue/dist/vue.runtime.common.dev.js:4459:25)
      at new Watcher (node_modules/vue/dist/vue.runtime.common.dev.js:4448:12)
      at mountComponent (node_modules/vue/dist/vue.runtime.common.dev.js:4055:3)
      at VueComponent.Object.<anonymous>.Vue.$mount (node_modules/vue/dist/vue.runtime.common.dev.js:8386:10)
      at mount (node_modules/@vue/test-utils/dist/vue-test-utils.js:8649:21)
      at shallowMount (node_modules/@vue/test-utils/dist/vue-test-utils.js:8677:10)
      at Object.it (src/test/weather_test/weatherTemp.test.js:24:21)

Test Suites: 1 failed, 2 passed, 3 total
Tests:       1 failed, 4 passed, 5 total
Snapshots:   0 total
Time:        63.368s
Ran all test suites.
npm ERR! Test failed.  See above for more details.

这是我的测试文件

import { shallowMount, createLocalVue } from "@vue/test-utils";
import Vuex from "vuex";
import weatherTemperature from "@/components/weather/weatherTemp.vue";

window.alert = jest.fn();
const localVue = createLocalVue();
localVue.use(Vuex);

describe("Getters.vue", () => {
  let getters;
  let store;

  beforeEach(() => {
    getters = {
      getTemperature: () => 2
    };

    store = new Vuex.Store({
      getters
    });
  });

  it('Renders "store.getters.clicks" in h1', () => {
    const wrapper = shallowMount(weatherTemperature, { store, localVue });
    const temp = wrapper.findAll(".weather-degree");
    expect(temp.text()).toBe(getters.getTemperature().toString());
  });
});

我的商店

import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export const store = new Vuex.Store({
  state: {
    coords: {},
    burgerClicked: false,
    temperature: 0,
    locationAllowed: false
  },
  getters: {
    getCoords(state) {
      return state.coords;
    },
    getBurgerClicked(state) {
      return state.burgerClicked;
    },
    getTemperature(state) {
      return state.temperature;
    }
  },
  mutations: {
    setCoords(state, value) {
      state.coords = value;
    },
    setBurgerClick(state, value) {
      state.burgerClicked = value;
    },
    setTemperature(state, value) {
      state.temperature = value.toFixed(0);
    },

    convertToCelsius(state) {
      var tempInCelsius = ((state.temperature - 32) * 5) / 9;
      state.temperature = tempInCelsius.toFixed(0);
    },
    convertToFarenheit(state) {
      var tempInFarenheit = state.temperature * (9 / 5) + 32;
      state.temperature = tempInFarenheit.toFixed(0);
    }
  },
  actions: {
    setCoords(context, value) {
      context.commit("setCoords", value);
    },
    setBurgerClick(context, value) {
      context.commit("setBurgerClick", value);
    },
    setTemperature(context, value) {
      context.commit("setTemperature", value);
    },
    convertToFarenheit(context) {
      context.commit("convertToFarenheit");
    },
    convertToCelsius(context) {
      context.commit("convertToCelsius");
    }
  }
});

我的Weathertemp组件

   <template>
      <div class="weather-temp">
        <h1 class="weather-degree">{{getTemperature}}&#176;</h1>
        <div class="weather-quote">
          <h1 class="weather-quote-1">
            <b>{{data.weather[0].main}}</b>
          </h1>
        </div>
      </div>
    </template>
    <script>
    import { mapGetters } from "vuex";
    export default {
      props: ["data"],
      computed: {
        ...mapGetters(["getTemperature"])
      }
    };
    </script>

调用setTemperature的主要组件

<template>
  <div class="main" v-if="weatherData.main">
    <Weather :data="weatherData" />
    <SideMenu :data="weatherData"/>
  </div>
</template>

<script>
import Weather from "./weather/weather";
import SideMenu from "./sidemenu/sideMenu";
import {mapActions, mapGetters } from "vuex";
export default {
  name: "Main",
  components: {
    Weather,
    SideMenu
  },
  data() {
    return {
      weatherData: {}
    };
  },
  methods: {
    ...mapActions(["setTemperature"])
  },
  created() {
    fetch(
      `https://api.openweathermap.org/data/2.5/weather?lat=${this.getCoords.coords.latitude}&lon=${this.getCoords.coords.longitude}&units=metric&APPID=${process.env.VUE_APP_APPID}`
    )
      .then(response => {
        return response.json();
      })
      .then(data => {
        console.log(data);

        this.weatherData = data;
        this.setTemperature(data.main.temp);
      });
  },
  computed: {
    ...mapGetters(["getCoords"])
  }
};

////////在下面忽略////////

Lorem Ipsum只是印刷和排版行业的伪文本。自1500年代以来,Lorem Ipsum一直是行业的标准伪文本,当时一位不知名的打印机拿起一个厨房,将其打乱成一本样本书。它不仅生存了五个世纪,而且在电子排版方面也取得了飞跃,但基本上没有改变。它在1960年代开始流行,发布了包含Lorem Ipsum段落的Letraset工作表,最近又发布了包括Alres PageMaker在内的桌面发行软件,包括Lorem Ipsum的版本。

1 个答案:

答案 0 :(得分:1)

问题是您正在尝试访问完全为undefined值的属性,在这种情况下为属性data。使用v-if之类的方法仅在定义数据并具有长度时渲染/访问该值:

<template>
  <div class="weather-temp">
    <h1 class="weather-degree">{{ getTemperature }}&#176;</h1>
    <div class="weather-quote">
      <h1 class="weather-quote-1">
        <b v-if="data && data.length">{{ data.weather[0].main }}</b>
      </h1>
    </div>
  </div>
</template>
<script>
import { mapGetters } from "vuex";
export default {
  props: ["data"],
  computed: {
    ...mapGetters(["getTemperature"])
  }
};
</script>

无论如何我都会推荐这种方法,因为您可能会在data尚未完全解决的情况下出现片刻,并且在生产中可能会遇到相同的错误,即除非您仅在Weathertemp中渲染父母有条件。否则,您需要使用propsData将prop data通过测试:

it('Renders "store.getters.clicks" in h1', () => {
  const propsData = { data: [{ weather: { main: 42 } }] };
  const wrapper = shallowMount(weatherTemperature, { store, localVue, propsData });
  const temp = wrapper.findAll(".weather-degree");
  expect(temp.text()).toBe(getters.getTemperature().toString());
});

希望有帮助!