How to address NodeJS's built-in functions with Sinon? - unit-testing

Using Sinon stubs, I have successfully stubbed functions along the project, using the traditional stubbing syntax:
const permissionsStub = sinon.stub(invitation, 'update')
sinon.assert.calledOnce(permissionsStub)
Now I am trying to Stub a built-in function of NodeJS (findIndex, indexOf, etc..), without success, as it should be passed with the in the first argument of Sinon's stub() function call, and as that is a NodeJS's core function, what needs to be passed?
I have tried creating an empty stub and then assigning it directly to the function in the code, but I think there is a simpler way to try and spy/stub/mock built-in NodeJS functions.
I get this error by trying to pass a few arguments that might target it correctly, as it doesn't succeed mounting:
TypeError: Cannot read property 'returns' of undefined
How can I target those functions in a simpler way using Chai and Sinon?

So eventually I got it to work using the following code (rewire is being used to get to the inner unexported functions of the file):
const permissionIndex = invitation.__get__('permissionIndex')
permissionsStub.findIndex = () => {
return { id: 1 }
}
expect(permissionIndex(1, permissionsStub)).to.be.an('object')
expect(permissionIndex(1, permissionsStub)).to.have.deep.property('id', 1)

Related

Mock extensions function inside Companion Object

I have a class (class A) to which I define an extension function (A.extension()) inside a companion object of another class (class B) for a matter of organization.
On my tests I need:
To use a real class A instance .
To mock A.extension().
To use a mock instance of class B.
Using MockK-library I am not being able to mock that extension function successfully.
I've tried:
mockkObject(B.Companion) {
every { any<A>().extension() } returns whatIneed
}
result: Tries to run the unmocked version of the extension function.
mockkStatic(path.to.B.CompanionKt)
every { any<A>().extension() } returns whatIneed
Result: It does not find the Companion Object.
mockkStatic(A::extension) {
every { any<A>().extension() } returns whatIneed
}
Result: Compile error -> 'extension' is a member and an extension at the same time. References to such elements are not allowed.
Am I missing something regarding how to mock this ?
Am I doing something wrong in terms of code structuring that prevents this mocking to be possible?
Any help is appreciated.
This seems to be an impossible thing. I have tried this severally and it does not work.

Testing response AND function call of library using fetch with Jest + node-fetch + fetch-mock

I'm writing a JavaScript/React library which uses fetch.
I'm using Jest in order to test this library, and what I'd like to achieve is :
Mock HTTP requests in order to not send real calls and manipulate the answers (mock the backend server) so I'm using fetch-mock
Test the passed parameters to the fetch function
In order to achieve the first point, I need to do
fetchMock.post(`${API_URL}/sessions`, {
body: JSON.stringify({
token: 'this-is-your-token'
}),
status: 201
})
In order to achieve the second point, I need to do
const spiedFetch = jest.spyOn(global, 'fetch')
// ...
expect(spiedFetch).toHaveBeenCalledTimes(1)
(The last line is within a series of describe() and it()).
I have a first test which ensures the response has the token field and so on, and the second test is ensuring that fetch has been called once.
When I run them, the first one passes, then second one fails. When I comment the fetchMock.post(...), the first one fails and the second one passes.
Based on this, I guess fetch-mock and jest.spyOn are incompatible.
Questions :
Am I right thinking fetch-mock and jest.spyOn are incompatible?
How can I achieve the testing of the fetch response AND the passed parameters? (I want to ensure the HTTP verb is this, and the passed headers are that).
A way I could think of is to use fetch-mock as is, but using jest.spyOn on a function of my lib, which would embed fetch. Is that an okay way of doing it?
UPDATE: I tried my point 3 and it works.
jest.spyOn replaces the original function with a wrapper.
const fetchMock = require('fetch-mock'); doesn't immediately change the global fetch, but as soon as a function like fetchMock.get is called it replaces the global fetch.
Because they both work by modifying the global fetch they can be tricky to use together.
As it turns out, every time a method like fetchMock.get is called the global fetch gets replaced, but if jest.spyOn is called after all such methods are called on fetchMock then they will actually both work since jest.spyOn will wrap and track the final replaced fetch.
Having said that, there isn't really a need to use jest.spyOn(global, 'fetch') if you are already using fetch-mock since fetch-mock provides access to all the calls that were made to fetch.
To assert on the calls directly you can access them using fetchMock.calls().
Even easier is to simply call fetchMock.done() at the end of the test to assert that fetch was used exactly as expected.

Is there a way to pass in complex arguments into Mocked Dart Services using Mockito?

I was looking at the documentation at: https://pub.dartlang.org/packages/mockito and was trying to understand it more. It seems that in the examples, the function stubs were accepting strings, but was kind of confused as to how I was going to implement my Mocked Services.
I was curious how I would do it. The services I have is pretty simple and straight forward.
class Group{}
class GroupService {}
class MockGroupService extends Mock implements GroupService {}
final mockProviders = [new Provider(MockGroupService, useExisting: GroupService];
So you can see I am using Angular dart.
I was creating a sample group in my Test file.
group("service tests", (){
MockGroupService _mock;
testBed.addProviders([mockProviders]);
setUp(() async {
fixture = await testBed.create();
_mock = new MockGroupService();
//This is where I was going to create some stubbs for the methods
when(_mock.add()).thenReturn((){
return null; //return the object.
});
//create additional when statements for edit, delete, etc.
});
});
So what i was thinking is that there would be an argument passed into add (or 2).... how would I properly code that in the when statement, and how do those 2 arguments reflect in the then statement?
Essentially, I was wanting to do a test with a complex class.. and pass it into add. Then it would just process it accordingly and return it.
Do i pass into the arguments something akin to: (using pseudocode)
when(_mock.add(argThat(hasType(Group)))).thenReturn((Group arg)=> arg);
or something similar? hasType isnt function, so im not 100% sure how to approach this design. Ideally, Im trying create the Group in the test, and then pass it into the add function accordingly. It just seems that the examples were showing Strings.
Yes mockito allows objects to be passed you can see examples in the test.
It is a bit hard to follow but you can see here that it uses deep equality to check if arguments are equal if no matchers are specified.
The second part of your question is a bit more complex. If you want to use the values that were passed into your mock as part of your response then you need to use thenAnswer. It provides you with an Invocation of what was just called. From that object you can get and return any arguments that were used in the method call.
So for your add example if you know what is being passing in and have complete access to it I would write:
Group a = new Group();
when(_mock.add(a)).thenReturn(a);
If the Group object is being created by something else I would write:
when(_mock.add(argThat(new isInstanceOf<Group>()))
.thenAnswer((invocation)=>invocation.positionalArguments[0]);
Or if you don't really care about checking for the type. Depending on what checks you are using for your test the type might already be checked for you.
when(_mock.add(any)).thenAnswer(
(invocation)=>invocation.positionalArguments[0]);
Or if you are using Dart 2.0:
when(_mock.add(typed(any))).thenAnswer(
(invocation)=>invocation.positionalArguments[0]);

Sinon stub instance method declared in mapDispatchToProps

New to testing and React Redux, so I may be conflating a few issues here. I will only present one example, but I have tried many different combinations of mount(), shallow(), instance(), stub, spy and more.
Given a component, where setFooData() updates redux state and Foo.props.data:
const mapDispatchToProps = (dispatch, props) => ({
setFooData(fooId, data) {
dispatch(Actions.setFooData(fooId, data));
},
});
...
return (
<div fooId={this.props.fooId}>
<Foo {...fooProps}/>
</div>
);
I would like to write some tests around the conditions under which setFooData() is called, namely conditions in lifecycle methods like componentDidMount() and componentWillReceiveProps().
Because setFooData() involves server calls and more, and because these tests merely concern the view layer and how the component renders as a result of Foo.props.data being set eventually by setFooData(), setFooData() seems like a good candidate for stub.
Therefore, Enzyme's shallow(), rather than mount(), seems appropriate, correct? In any case, when I try to stub setFooData():
let wrapper = return shallow(<Foo {...props}/>);
let stub = sinon.stub(wrapper.instance(), 'setFooData');
I receive the error:
Attempted to wrap undefined property setFooData as function
Upon inspection, wrapper.instance() yields an object where setFooData() is indeed not defined, but according to other examples, I would think it should be.
Furthermore, setFooData() does exist on wrapper.instance().selector.props, and while let stub = sinon.stub(wrapper.instance().selector.props, 'setFooData'); avoids the error, when I inspect the object setFooData() =/= stub, and the function is not called as per the test.
When I use mount() instead,
let wrapper = mount(<Provider store={store}><Foo {...props}/></Provider>);
let componentDidMountSpy = sinon.spy(Foo.prototype, 'componentDidMount');
let componentWillReceivePropsSpy = sinon.spy(Foo.prototype, 'componentWillReceiveProps');
expect(componentDidMountSpy.called).to.be.true; //passes
expect(componentWillReceivePropsSpy.called).to.be.true; //passes
expect(stub.called).to.be.true; //fails
I receive a different error that appears related to the body of setFooData(), so setFooData() is called but the function is not actually stubbed to prevent its real body from being executed.
Thanks for any help to clarify my understanding.
I think you're taking the hardest path. You should test your component in isolation, not the connected one. If you test the connected component you're making an integration test and double testing that connect indeed works. That's already tested in react-redux for you.
Instead, test your action creators by themselves in unit tests.
Then, export your component as named export without connecting and use the default export for the connect version.
That way you can simply import the pure-React version and pass anything you want as props, in order to make easy assertions afterwards.
If you need to specifically test that something happens in those lifecycle methods, you can call those methods from the instance:
const fakeActionCreator = sinon.spy()
const subject = mount(<MyComponent doSomething={ fakeActionCreator } />)
subject.instance().componentDidMount()
assert.equal(fakeActionCreator.callCount, 1)

How do I check if the Create method was called using Expect instead of AssertWasNotCalled in Rhino Mocks?

How do I check if Create was not called without using the Rhino Mocks AssertWasNotCalled method.
Here is the test:
[Test]
public void When_try_to_create_directory_that_already_exits_return_false()
{
var directoryInfoMock = MockRepository.GenerateMock<IDirectoryInfoWrap>();
directoryInfoMock.Stub(x => x.Exists).Return(true);
directoryInfoMock.Expect(x => x.Create());
Assert.AreEqual(false, new DirectoryInfoSample().TryToCreateDirectory(directoryInfoMock));
directoryInfoMock.VerifyAllExpectations();
}
Also, can someone clarify what Stub does.
directoryInfoMock.Stub(x => x.Exists).Return(true);
ensures that any call to the property directoryInfoMock.Exists will return true. But if the property is never call or called many times, it will not cause the test to fail. The purpose of the stub is to provide some meal to your code under test so that it can run normally.
directoryInfoMock.Expect(x => x.Create());
expects that the method directoryInfoMock.Create be called at least once. If not, an exception will be thrown by Rhino.Mocks during the execution of directoryInfoMock.VerifyAllExpectations().
So basically, your unit test should work as expected. What is the output of the test?
UPDATE:
You might want to specify an explicit number of times the method should be called as well. This can be done by using Repeat.x with x is Once(), Twice(), Never(), or Times(N).
directoryInfoMock.Expect(x => x.Create()).Repeat.Never();
This expects that Create is never called. And of course your test will fail if it is actually called.
If you need to make sure that only the methods you expect are called you can consider using strict mocks. Then you will get an exception when a method was called that was not expected on your mock, the only change to your code is when you create your mock:
var directoryInfoMock = MockRepository.GenerateStrictMock<IDirectoryInfoWrap>();
if you know exactly which method shouldn't be called its better to use AssertWasNotCalled (you use it after your test was executed). This way you don't tie your test with your code so closely.