goatslacker / goatslacker/alt

Understanding unittesting of stores

Open
#680 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
JavaScript
Stars
3.4k
Forks
312
PR merge metrics
No merged PRs in 30d

Description

Hi there, I got some problems related to testing alt stores. I am using the altTestingUtils form alt-utils. There, methods seem to return values in different ways when setting store data directly of via setState().

Take the following example:

``` javascript
// The example store:
import alt from './Dispatcher';
import Actions from './Actions';
import Source from './Source';

export class ExampleStore {
constructor() {

this.bindActions(Actions);
this.registerAsync(Source);

this.state = {
x: false
};
}

onSetXDirect() {
this.state.x = true;
}

onSetXImmutable() {
this.setState({ x: true });
}
}

export default alt.createStore(ExampleStore, 'ExampleStore');
```

Now, take the following test (import paths changed for better readability):

``` javascript
import AltTestingUtils from 'alt-utils/lib/AltTestingUtils';
import alt from './Dispatcher';
import Actions from './Actions';
import WrappedStore, { ExampleStore } from './Store';

describe('ExampleStore', function () {

let storeClass;
beforeEach(function () {
alt.recycle(WrappedStore);
storeClass = AltTestingUtils.makeStoreTestable(alt, ExampleStore);
});

// This will work without any problems
describe('when using onSetXDirectly', function () {
expect(storeClass.state.x).to.be.false;
storeClass. onSetXDirectly();
expect(storeClass.state.x).to.be.true;
});

// This wont work, as storeClass.state is still the old one
describe('when using onSetXImmutable', function () {
expect(storeClass.state.x).to.be.false;
storeClass. onSetXImmutable();
expect(storeClass.state.x).to.be.true;
});

// This wont work either, thought it would just update the WrappedStore, but no...
describe('when using onSetXImmutable', function () {
expect(storeClass.state.x).to.be.false;
storeClass. onSetXImmutable();
expect(WrappedStore.getState().x).to.be.true;
});

// This will in fact work...
describe('when using onSetXImmutable with action triggered', function () {
expect(WrappedStore.getState().x).to.be.false;
Actions.setXImmutable();
expect(WrappedStore.getState().x).to.be.true;
});
});
```

I would expect that when using the the wrapped store (parsed through AltTestingUtils.makeStoreTestable) it also should get the updated data after using setState().

Also I got another issue with makeStoreTestable. Imagine the following code:

``` javascript
class Example {

static doRemote() {
return new Promise((resolve) => {
window.setTimeout(() => {
resolve({ id: 5 });
}, 500);
});
}

doSomething() {
this.getInstance().doRemote().then(data => {
this.setState(data);
});
}
}
```

I do not think that this does any harm. I am using a custom doRemote method that can be statically called from within and out of the store. Imagine a sources remote method here that was bound via this.exportAsync() in the constructor of the store.

The code itself works really well. However, if I try to test with makeStoreTestable, it will tell me that doRemote is not accessible. This happens, because makeStoreTestable will exchange the getInstance()-method with an empty function, returning undefined. My current workaround for this is quite ugly:

``` javascript
let storeClass;
beforeEach(function () {
alt.recycle(WrappedStore);
storeClass = AltTestingUtils.makeStoreTestable(alt, ExampleStore);
storeClass.getInstance = function () {
return WrappedStore;
};
});
```

This will work, as it returns the original base class. However, I cannot think that this should be the recommended way to test such stuff.

Hope to get some input, would be really appreciated.

Thanks in advance,
Chris

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.