Mike Martin
Mike Martin

Reputation: 88

Setup testing with MobX store circular references

I am trying to figure out testing with Jest for my MobX stores.

I am using Mobx, React, and Jest.

class ConfigStore {
    constructor(RootStore) {
        this.rootStore = RootStore;
        this.config = {};
    }
}
class DataStore {
    constructor(RootStore) {
        this.config = RootStore.config;
    }
}
class UIStore {
    constructor(RootStore) {
        this.config = RootStore.config;
        this.data = RootStore.data;
    }
}
class RootStore {
    constructor() {
        this.config = new ConfigStore(this);
        this.ui = new UIStore(this);
        this.data = new DataStore(this);
    }
}

Did I set my stores up correctly?

If so, what is the best way to test the stores before they get passed to Provider?

Upvotes: 2

Views: 778

Answers (1)

Joel Harkes
Joel Harkes

Reputation: 11661

Your question is very unclear. What exactly do you want to test about these stores in unit tests? You can't really test data itself.

My suggestions:

link to stores

instead of using setting a single property just keep the whole store:

class DataStore {
    constructor(RootStore) {
        this.configStore = RootStore;
    }
}

this way you can besure properties are always properly updated and observed.

if you want you can always have property on your lower level stores:

class DataStore {
    constructor(RootStore) {
        this.configStore = RootStore;
    }
    get config() {
       return this.configStore.config;
    }
}

Abstract

if you use typescript abstract your stores with interfaces so the stores are way easilier tested:

class DataStore {
    constructor(store: IConfigStore) {
        this.configStore = store;
    }
}
interface IConfigStore {
     config: Config;
}

Use a repository pattern

For every store make a repository injectable so that all api calls done by the store are actually done in this repository:

class RootStore {
    constructor(repository) {
        this.repostiory = repository;
        this.config = new ConfigStore(this);
        this.ui = new UIStore(this);
        this.data = new DataStore(this);
        this.initializeData();
    }
    async initializeData(){
         this.config = await this.repository.getConfig();
    }
}

This way you can easily mock the repository to give static date so you dont need to do any api calls.

Keep your react components pure

The react components that you really want to unit test. make sure they dont use mobx stores directly but you use the inject() function instead to make a second class: https://github.com/mobxjs/mobx-react#inject-as-function

this way your components are way easilier testable and useable stand alone:

const PureReactComponent = ({ name }) => <h1>{name}</h1>

const SimpleMobxComponent = inject(stores => ({
    name: stores.userStore.name
}))(PureReactComponent)

// usage:
render() {
  return <SimpleMobxComponent/>
}

Upvotes: 2

Related Questions