For mocking uuidv4, I am using this :
import { v4 as uuidv4 } from "uuid";
jest.mock("uuid");
uuidv4.mockReturnValue("uuid123");
And for mocking window.confirm, I am using this:
window.confirm = jest.fn().mockImplementation(() => true);
These both are working all right.
But when i try doing this i.e
const uuidv4 = jest.fn.mockImplementation(() => "uuid123");
I get this error
TypeError: jest.fn.mockImplementation is not a function
I am confused between jest.fn() and jest.mock().
Can someone please elaborate on which one to use and when to use, with suitable example?
Just a quick explanation for you:
jest.mock is to mock a certain module. Once you write jest.mock('uuid') then it means all exported things would be turned to a jest.Mock type, that's why you can mock v4 method: v4.mockReturnValue('yourV4Id');
jest.mock('aModule');
import {aMember} from "aModule";
// is now a jest mock type <=> jest.fn()
aMember.mockReturnValue('a value');
jest.fn is a function which returns a jest.Mock type which can be considered as an function to create whatever you want:
const aMock = jest.fn().mockReturnValue(1) // <=> const aMock = () => 1;
// The difference is jest mock type can be used to assert then. Most of cases is to check
// whether it gets called or not
When I tried to do unit testing for private methods in a Class getting error as private methods are only accessible inside the class. Here I added sample snippet for my class and mocha test. Kindly provide me solution to implement unit test for private methods.
Class Name: Notification.ts
class Notification {
constructor() {}
public validateTempalte() {
return true;
}
private replacePlaceholder() {
return true;
}
}
Unit Test:
import {Notification} from 'Notification';
import * as chai from "chai";
describe("Notification", function(){
describe('#validateTempalte - Validate template', function() {
it('it should return success', function() {
const result = new Notification()
chai.expect(result.validateTempalte()).to.be.equal(true);
});
});
describe('#replacePlaceholder - Replace Placeholder', function() {
it('it should return success', function() {
const result = new Notification()
// As expected getting error "Private is only accessible within class"
chai.expect(result.replacePlaceholder()).to.be.equal(true);
});
});
});
As a workaround, currently, I am changing access specifier of function replacePlaceholder to public. But I don't think its a valid approach.
A possible solution to omit Typescript checks is to access the property dynamically (Not telling wether its good).
myClass['privateProp'] or for methods: myClass['privateMethod']()
Technically, in current versions of TypeScript private methods are only compile-time checked to be private - so you can call them.
class Example {
public publicMethod() {
return 'public';
}
private privateMethod() {
return 'private';
}
}
const example = new Example();
console.log(example.publicMethod()); // 'public'
console.log(example.privateMethod()); // 'private'
I mention this only because you asked how to do it, and that is how you could do it.
Correct Answer
However, that private method must be called by some other method... otherwise it isn't called at all. If you test the behaviour of that other method, you will cover the private method in the context it is used.
If you specifically test private methods, your tests will become tightly coupled to the implementation details (i.e. a good test wouldn't need to be changed if you refactored the implementation).
Disclaimer
If you still test it at the private method level, the compiler might in the future change and make the test fail (i.e. if the compiler made the method "properly" private, or if a future version of ECMAScript added visibility keywords, etc).
In my case, I use the prototype of the object to get access to a private method. It works well and TS does not swear.
For example:
class Example {
private privateMethod() {}
}
describe() {
it('test', () => {
const example = new Example();
const exampleProto = Object.getPrototypeOf(example);
exampleProto.privateMethod();
})
}
If you use a static method then use exampleProto.constructor.privateMethod();.
In HolgerJeromin's comment, the comment issue has a succinct solution that still uses the property syntax.
The solution is to type cast your object / class to any.
Examples:
(<any>myClass).privateMethod();
const value = (<any>myClass).privateValue;
(myClass as any).privateMethod();
const value = (myClass as any).privateValue;
This method satisfies the compiler as well as the VSCode syntax highlighting.
Here are some of my notes from the issue that talks about this
Accessing via a string is more common, although I don't see why it might be more typesafe.
These features are done deliberately, therefore they are helping more than hindering.
There is probably a way to disable this type of feature so people don't copy and paste this code into production. "noImplicitAny": true, might help in the tsconfig.json
Extract out the private function into a separate/stand alone function, but don't export it externally.
This is somewhat semantically correct, since after all — a private function is private and should not be accessed by anyone except the class itself.
My subjective solution: you could define a new testing-only interface that extends the original one by adding the private methods as (implicitly public) interface methods. Then, you cast the instantiated object to this new test type. This satisfies both tsc and VS code type checking. Your example with my solution:
interface INotification {
validateTemplate(): boolean,
}
class Notification implements INotification {
constructor() {}
public validateTemplate() {
return true;
}
private replacePlaceholder() {
return true;
}
}
Testing:
import {Notification} from 'Notification';
import * as chai from "chai";
interface INotificationTest extends INotification {
replacePlaceholder(): boolean;
}
describe("Notification", function(){
describe('#validateTemplate - Validate template', function() {
it('it should return success', function() {
const result = new Notification() as INotificationTest;
chai.expect(result.validateTemplate()).to.be.equal(true);
});
});
describe('#replacePlaceholder - Replace Placeholder', function() {
it('it should return success', function() {
const result = new Notification() as INotificationTest;
// Works!
chai.expect(result.replacePlaceholder()).to.be.equal(true);
});
});
});
Advantages:
tsc and vs code do not complain
IntelliSense (or any other autocomplete) works
simple (subjectively)
If you don't want to define the original interface (INotification), you could just fully define the test one (INotificationTest) instead of extending and cast it in the same manner.
Disadvantages:
Added boilerplate
Need to have both of the interfaces updated and in sync
Potentially introducing bugs by explicitly casting as a non original type.
I leave it up to you to decide whether this is worth it or no. In my case, the positives outweigh the negatives. I have tested this with jest, but I assume that mocha.js is no different here.
Edit: but generally I would agree with Fenton's answer
// module.ts
private async privateMethod = () => "private method executed"
public async testPrivateMethods(...args) {
if (process.env.NODE_ENV === 'development') {
return this.privateMethod(...args);
}
}
Now we can reach our private method to test. In jest file:
// module.spec.js
describe('Module', () => {
let service: Module = new Module();
it('private method should be defined', () => {
expect(service.testPrivateMethods).toBeDefined();
});
}
You need to set your enviroment variable name of NODE_ENV must be development.
// .env
NODE_ENV="development"
The fun thing is that it's just a typescript error (not javascript), so you can fix it with
// #ts-expect-error
and everything works fine.
I consider it as a legitimate solution, as the goal was to suppress typescript in this particular case.
Since private methods are not accessible outside class, you can have another public method which calls replacePlaceholder() in Notification class and then test the public method.
I have an epic with the following signature (note the dependency)
export const incrementalSearchEpic = (action$, store, { incrementalSearchService }) => {
// eslint-disable-next-line max-len
return action$.ofType('SEARCH_STORES').mergeMap((action) =>
incrementalSearchService.performIncrementalSearch(action)
);
};
Now I need to unit test this and this is my unit testing code
beforeEach(() => {
epicMiddleWare = createEpicMiddleware(incrementalSearchEpic,
{
dependencies: {
incrementalSearchService: IncrementalSearchServiceMock
}
});
const mockStore = configureMockStore([epicMiddleWare]);
const getState = {}; // initial state of the store
store = mockStore(getState);
});
// eslint-disable-next-line max-len
it('calls the incrementalSearchService->performIncrementalSearch with the parameters when called', () => {
//dispatch the incremental search action
const searchStore = {
type: 'SEARCH_STORES',
SearchText: 'Aldi'
};
store.dispatch(searchStore);
expect(store.getActions()).toEqual([
searchStore
]);
});
However when I run the code I get the following error
TypeError: Cannot read property 'performIncrementalSearch' of undefined
Seems like the dependency does not get passed in properly.
I just realized: if redux-observable wasn't injecting the provided dependencies object you'd actually get Cannot read property 'incrementalSearchService' of undefined not performIncrementalSearch because redux-observable does not inject an object by default--it's not erroring because it is indeed passing your object.
Instead, the likely problem is that your import or definition of IncrementalSearchServiceMock is actually undefined. Perhaps a wrong named import or similar.
If you can't immediately see why, pause your debugger at the beginning of beforeEach and confirm the value of IncrementalSearchServiceMock is not undefined.
I'm using Meteor 1.0.
I have a Template.*name*.rendered function that makes a number of calculations. At the end of the calculations, I would like the output to make its way into a Template.*name*.helpers so I can use it in the corresponding html page.
Here's a simplified version of the code:
Template.myTemplate.rendered = function () {
var x = Math.random();
Template.otherTemplate.helpers({
randomNum: x
});
}
When I call {{randomNum}} in otherTemplate, nothing happens.
I have also tried putting the Template.*name*.helpers outside of Template.*name*.rendered, in which case, I get the error:
Uncaught ReferenceError: x is not defined
Thoughts?
This isn't really the right way of going about things as the way Meteor works is by compiling templates before the application starts, rather than at run-time. Whilst something along these lines may be possible (for example by using Template.registerHelper), it would be much better to set a reactive variable to a specific value in the rendered callback and have the helper set to return that instead:
Session.setDefault('randomNum', 0);
Template.myTemplate.rendered = function () {
Session.set('randomNum', Math.random());
}
Template.otherTemplate.helpers({
randomNum: Session.get('randomNum')
});
If you'd rather use a private variable for the randomNum, have a look at ReactiveVar. It could be any reactive data source and it would work.
You used to create helpers as an object of the template but since Meteor has deprecated that you now have to create the helpers within the helper function.
Now in order to call the helper via javascript you must use this function
Template.*TemplateName*.__helpers.get('*HelperName*')(*Params*);
Its a pretty simple way of doing this and it keeps the functions out of the global scope so its pretty clean.
Here is an example of how I am using this
~~~
Template.home.events({
'click .pair': function(event) {
var _this = $(event.currentTarget);
Template.home.__helpers.get('pairDevice')(_this);
}
});
Template.home.helpers({
'devices' : function() {
return Session.get('devices');
},
'pairDevice' : function(elm) {
elm.fadeOut();
$('.home-page').addClass('paired');
var deviceList = [
{
'name' : 'Patrick\'s Phone',
'UUID' : '234123,4n123k4nc1l2k3n4 l1k23n4l12k3nc4l12'
},
{
'name' : 'Mike\'s Phone',
'UUID' : '734k23k4l2k34l2k34l2k34l2k3m'
},
{
'name' : 'Edgar\'s Phone',
'UUID' : '567k56l7k4l56k7l5k46l74k56l74k5'
}
];
Session.set('devices', deviceList);
}
});
~~~
I need to shim a static generic method for a unit test. However, I can't seem to get Fakes to create the shim object. Does anyone know how to accomplish this?
In particular, I want to shim Newtonsoft's JsonConvert.DeserializeObject<>()
For each return type that you would expect register a delegate like so:
With this code in the Unit Test:
using (var context = ShimsContext.Create())
{
ShimJsonConvert.DeserializeObjectOf1String<SomeJSonObject>(s => new SomeJSonObject() { Name = "Foo" });
SomeJSonObject o = ConsoleApplication3.Program.Deserialize();
Assert.IsNotNull(o);
Assert.AreSame(o.Name, "Foo");
}
And this code under test:
return JsonConvert.DeserializeObject<SomeJSonObject>("");
It works as expected for me.
If needed also register the other overloads. So if you're using some of the other overloads, you must also register their corresponding delegates on the Shim:
Like:
ShimJsonConvert.DeserializeObjectOf1String<SomeJSonObject>(s => new SomeJSonObject() { Name = "Foo" });
ShimJsonConvert.DeserializeObjectOf1StringJsonConverterArray((s, convertors) => new SomeJSonObject() {Name = "Bar"});
ShimJsonConvert.DeserializeObjectOf1StringJsonSerializerSettings((s, settings) => new SomeJSonObject() { Name = "Bar" });