mocha: Cannot read property 'be' of undefined - node.js

I'm writing unit test for my project. But I always meet this problem
Cannot read property 'be' of undefined.
I have a test suite called model-xxx, and I wanna try each method in this model. So each method I write a sub test suite in model-xxx. like this:
enter image description here
And each method is related with mongoose, so I hope these sub suite will be async. so each method I write done() in before and after and it
but none of these suite passed. error like this:
enter image description here
and like this:
Cannot read property 'not' of undefined.
why this occurs? does this mean something wrong with my should.js? but it doesn't make sense
hope for solutions.

Chai's should is a function that needs to be called before you can use should-style assertions:
var should = require('chai').should();
See the documentation.

Related

Jest how to assert that function is not called

In Jest there are functions like tobeCalled or toBeCalledWith to check if a particular function is called.
Is there any way to check that a function is not called?
Just use not.
expect(mockFn).not.toHaveBeenCalled()
See the jest documentation
not did not work for me, throwing a Invalid Chai property: toHaveBeenCalled
But using toHaveBeenCalledTimes with zero does the trick:
expect(mock).toHaveBeenCalledTimes(0)
Recent versions of Jest (22.x and onwards) collect quite decent statistics of mock functions calls, just check out their docs.
The calls property shows you the number of calls, the arguments passed to the mock, the result returned out of it and whatnot. You can access it directly, as a property of mock (e.g. in a way how #Christian Bonzelet suggested in his answer):
// The function was called exactly once
expect(someMockFunction.mock.calls.length).toBe(1);
// The first arg of the first call to the function was 'first arg'
expect(someMockFunction.mock.calls[0][0]).toBe('first arg');
// The second arg of the first call to the function was 'second arg'
expect(someMockFunction.mock.calls[0][1]).toBe('second arg');
I personally prefer this way as it gives you more flexibility and keeps code cleaner in case if you test for different inputs that produce a different number of calls.
However, you can also use shorthand aliases for Jest's expect since recently (spy matchers aliases PR). I guess .toHaveBeenCalledTimes would suit fine here:
test('drinkEach drinks each drink', () => {
const drink = jest.fn();
drinkEach(drink, ['lemon', 'octopus']);
expect(drink).toHaveBeenCalledTimes(2); // or check for 0 if needed
});
In rare cases, you might even want to consider writing your own fixture that'd do the counting. It could be useful if you're heavy on conditioning or working with state, for example.
Hope this helps!
Please follow the documentation from jest:
https://jestjs.io/docs/en/mock-functions#mock-property
All mock functions have this special .mock property, which is where data about how the function has been called and what the function returned is kept. The .mock property also tracks the value of this for each call, so it is possible to inspect this as well: [...]
These mock members are very useful in tests to assert how these functions get called, instantiated, or what they returned:
// The function was called exactly once
expect(someMockFunction.mock.calls.length).toBe(1);
Or...
// The function was not called
expect(someMockFunction.mock.calls.length).toBe(0);

Unit tests with chai and Eshint are not passing

Hope you can help, recently moved from jshint to eslint and Im looking to see how to get my tests to pass wihtout making changes;
Take for exmaple the following test
expect(ctrl.screens).to.not.be.undefined;
eshint complains with the following expection;
error Expected an assignment or function call and instead saw an expression no-unused-expressions
Changing the test to;
expect(ctrl.screens).to.not.be.undefined();
Gives the following error:
TypeError: '[object Object]' is not a function (evaluating 'expect(ctrl.screens).to.not.be.undefined()')
Any ideas what approach to take here? All the tests pass when I remove eshint from the task list so I need for some way to clean up these tests.
J
Testing for undefined is tricky. There are some alternative ways to do it. I normally check for typeof(variable) === 'undefined.
Example:
expect(typeof(ctrl.screens)).to.not.equal('undefined');

doesNotThrow in Node.js returns undefined

In my NodeUnit tests, I have such a piece of code:
exports['aTest'] = function(test){
...
var functionResult = test.doesNotThrow(aFunction(aParam));
...
}
But functionResult is undefined after the call to doesNotThrow(...)
Why does test.doesNotThrow() not return the result of the function call?
That would be quite elegant.
It doesn't return anything as shown in the source code, this is because nodeunit relies on AssertionError to determine if a suite succeeded or not, as you could see here
Why would you want it to return something, what return value would you expect?
The purpose of the library is to test your assertions. It should not return a value since that would mean giving you info to do something with that value, instead, when an assertion throws you will get a console message saying that your tests got broken. I believe this is a good approach.
Your goal is to be notified when something brokes, relying on the library to tell you what broke, not to delve yourself into the details, that is why I believe the author chose this way.

Mockito mocking with Enum parameter not working

I can't figure out what is wrong with this, hopefully someone can help:
I have an enum, MyEnum that is used as a parameter to a method I am trying to mock. The mocking looks a bit like this:
when(myMockedObject.getMethod(MyEnum.XYZ)).thenReturn(myMockedValue);
and the actual code execution looks like this:
MyMockedValue theMockedValue = myMockedObject.getMethod(MyEnum.XYZ);
I'm expecting theMockedValue to equal myMockedValue. However, the mocking is not working and theMockedValue is always null. What is wrong with this?
This was down to my own dodgy code. I found a duplicated mock object, one instance was involved in the mocking and the other was being used in the code, resulting in null values being returned.
Just as I thought I was losing the battle with mockito and now I realise I do understand what is going on.

Wanted but not invoked: However, there were other interactions with this mock:

Wanted but not invoked: However, there were other interactions with this mock:
This is a mockito error you would catch when trying to verify the invocation on an object on specific method, but what happens is you have interacted with other method of that object but not the one mentioned.
If you have an object named CustomerService and say it has two methods named saveCustomer() and verifyExistingCustomer(),
and your mockito looks something like verify(customerService, atleast(1)).verifyExistingCustomer(customer), but in your actual service you called the saveCustomer() at least one.
Any idea how to resolve this ?
From what you are describing, it looks like you are telling your mocks that you are expecting verifyExistingCustomer() to be called but you are not actually calling it.
You should probably look at your test design, specifically ensuring that you can (via mocking) isolate your tests to test each method individually.
If there is something in your code that decides whether to call saveCustomer() or verifyExistingCustomer() then you should try to mock the data that the code inspects so that you can test each individually.
For example if your code looked like this:
if (customer.getId() == 0) {
saveCustomer(customer);
} else {
verifyExistingCustomer(customer);
}
Then you could have two separate tests that you could isolate by setting a zero value and non-zero value for the id in customer.
If you'd like to share your code I could probably give you a better example.

Resources