4
votes

I'm trying to test my React components using Mobx stores with Jest and React-testing-library.

The problem is that I have no clues on how to inject my stores for the test.


Here is my simplified codes.

StaffInfo.js(component)

import React, { useState } from "react";
import { observer, inject } from "mobx-react";

const StaffInfo = props => {
   const store = props.instituteStore;
   const [staffs, setStaffs] = useState(store.staffs);

   return (
      <div>
         ....
      </div>
   );
}

export default inject(rootStore => ({
    instituteStore : rootStore.instituteStore
}))(observer(StaffInfo));


index.js(Root store)

import LoginStore from "./LoginStore";
import InstituteStore from "./InstituteStore";

class RootStore {
    constructor(){
        this.loginStore = new LoginStore (this);
        this.instituteStore = new InstituteStore(this);
    }
}

export default RootStore;


InstituteStore.js(target store)

import { observable, action } from "mobx";

class InstituteStore {
    constructor(root){
        this.root = root;
    }

    @observable
    staffs = [];
}

export default InstituteStore;


StaffInfo.test.js(test file)

import React from "react";
import ReactDom from "react-dom";
import { MemoryRouter } from "react-router-dom";
import { Provider } from "mobx-react";

import StaffInfo from "./StaffInfo";
import InstituteStore from "../stores/InstituteStore";

describe("Staff Component testing", () => {
    test("should be rendered without crashing", () => {
        const div = document.createElement("div");
        ReactDOM.render(
            <MemoryRouter initialEntries={["/staff"]}>
                <StaffInfo instituteStore={RootStore.instituteStore} />
            </MemoryRouter>,
            div
        );
        ReactDOM.unmountComponentAtNode(div);
    });
});

As soon as running this test file, the error messages are like :

TypeError : Cannot read property 'staffs' of undefined

Please tell me which parts of the codes are wrong. Thanks so much in advance!

2
use Provider from mobx-react in your app.js to pass the mobx stores to deeply nested childs - uneet7
Thanks for the comment but I've already used Provider in my app.js. Do I have to declare app.js in my test to pass the stores? - dorong
After trying several things, I've finally figured out that declared codes like <Provider {...root} ><App><StaffInfo /></App> in my test file work well. You saved my day. Thank you so much - dorong

2 Answers

5
votes

Mobx-react's Inject is used to insert stores to the deep child component. These stars are provided by the context-based API Provider.

so wherever you are providing the stores to the child components use something like.

import rootStore from 'path_to_rootStore'
<Provider rootStore={rootStore}>
...
... 
 <App/>
...
...
<.Provider>
0
votes

Thanks to @uneet7:

Legend! Finally someone gave a sensible answer :D This is what My component looks like and

@inject('routing', 'navigationStore')
@observer
export default class PageTitle extends React.Component<*> {...}

And this is how I made it work:

let view = mount(
      <Provider {...getStores()}>
        <UserPage notificationStore={notificationStore} routing={routing} />
      </Provider>
    );

So the UserPage has components (many) and one of those components has PageTitle component. Obviously PageTitle has the @inject on it. It doesn't matter, as Provider HOC will provide stores via inject function to the component props.