5

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!

skyboyer
  • 22,209
  • 7
  • 57
  • 64
dorong
  • 65
  • 1
  • 2
  • 5
  • 1
    use `Provider` from `mobx-react` in your app.js to pass the mobx stores to deeply nested childs – uneet7 Sep 30 '19 at 11:45
  • 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 Oct 01 '19 at 02:20
  • 1
    After trying several things, I've finally figured out that declared codes like `` in my test file work well. You saved my day. Thank you so much – dorong Oct 01 '19 at 03:38

2 Answers2

4

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>
uneet7
  • 2,925
  • 7
  • 24
  • 41
  • 1
    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( ); ``` – George Mylonas Nov 26 '19 at 18:16
1

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.

George Mylonas
  • 704
  • 6
  • 16