admin管理员组文章数量:1131439
is it possible to use Jasmine unit testing framework's spyon method upon a classes private methods?
The documentation gives this example but can this be flexible for a private function?
describe("Person", function() {
it("calls the sayHello() function", function() {
var fakePerson = new Person();
spyOn(fakePerson, "sayHello");
fakePerson.helloSomeone("world");
expect(fakePerson.sayHello).toHaveBeenCalled();
});
});
is it possible to use Jasmine unit testing framework's spyon method upon a classes private methods?
The documentation gives this example but can this be flexible for a private function?
describe("Person", function() {
it("calls the sayHello() function", function() {
var fakePerson = new Person();
spyOn(fakePerson, "sayHello");
fakePerson.helloSomeone("world");
expect(fakePerson.sayHello).toHaveBeenCalled();
});
});
Share
Improve this question
edited Nov 28, 2022 at 13:18
xav
5,6087 gold badges50 silver badges58 bronze badges
asked Dec 12, 2011 at 14:09
user502014user502014
2,3215 gold badges24 silver badges32 bronze badges
0
13 Answers
Reset to default 219Just add a generic parameter < any> to the spyon() function:
spyOn<any>(fakePerson, 'sayHello');
It works on perfectly !
spyOn<any>(fakePerson, 'sayHello');
expect(fakePerson['sayHello']).toHaveBeenCalled();
by adding <any>
to spyOn you remove it from typescript type check.
you also need to use array index notation in order to access a private method (sayHello) in the test expect
Let say sayHello(text: string)
is a private method. You can use the following code:
// Create a spy on it using "any"
spyOn<any>(fakePerson, 'sayHello').and.callThrough();
// To access the private (or protected) method use [ ] operator:
expect(fakeperson['sayHello']).toHaveBeenCalledWith('your-params-to-sayhello');
- Create a spy on private method using
any
. - To access the private (or protected) method use
[]
operator.
if you use Typescript for your objects, the function isn't really private.
All you need is to save the value that returned from spyOn
call and then query it's calls
property.
At the end this code should work fine for you (at least it worked for me):
describe("Person", function() {
it("calls the sayHello() function", function() {
var fakePerson = new Person();
// save the return value:
var spiedFunction = spyOn<any>(fakePerson, "sayHello");
fakePerson.helloSomeone("world");
// query the calls property:
expect(spiedFunction.calls.any()).toBeFalsy();
});
});
spyOn(fakePerson, <never>'sayHello');
spyOn(fakePerson, <keyof Person>'sayHello');
Both silence the type error and don't interfere with TSLint's no-any
rule.
In my case (Typescript):
jest.spyOn<any, string>(authService, 'isTokenActual')
OR with mocked result:
jest.spyOn<any, string>(authService, 'isTokenActual').mockImplementation(() => {
return false;
});
There is an update to the context of this question, in
regard to what "private" means. As of ES2022, JavaScript has private class fields, that are prefixed with a hash (#). These properties are truly private, and even with the solutions suggested, cannot be spyOn()
ed.
fakePerson['sayHello'] = jasmine.createSpy().and.callThrough();
expect(fakePerson['sayHello']).toHaveBeenCalled();
Typescript gets compiled to javascript and in javascript every method is public. So you can use array index notation to access private methods or fileds, viz:
Object['private_field']
If you want to test private functions within a class, why not add a constructor to your class that signals that those private functions get returned?
Have a read through this to see what I mean: http://iainjmitchell.com/blog/?p=255
I have been using a similar idea and so far its working out great!
When your class looks like this
class SomeClass {
private method(){}
}
In test you can do
// @ts-ignore
class SomeClassForTest extends SomeClass {
public method(){}
}
let service: SomeClassForTest = TestBed.inject(SomeClass) as any;
IMHO it is better than using , because you dont have to do it on each line.
No cause you cant access a private function outside the context of your instance.
Btw, its not a good idea to spy on objects you wanna test. When you test if a specific method in your class you want to test is called, it says nothing. Lets say you wrote the test and it passed, two weeks later you refactor some stuff in the function and add a bug. So your test is still green cause you the function called. B
Spies are useful when you work with Dependency Injection, where all external dependencies are passed by the constructor and not created in your class. So lets say you have a class that needs a dom element. Normaly you would use a jquery selector in the class to get this element. But how you wanna test that something is done with that element? Sure you can add it to your tests pages html. But you can also call your class passing the element in the constructor. Doing so, you can use spy to check if your class interacts with that element as you expected.
const spy = spyOn<any>(component, 'privateMethod');
expect(spy).toHaveBeenCalled();
To avoid lint warnings regarding object access via string literals, create a local constant of the spy object.
本文标签: javascriptusing Jasmines spyon upon a private methodStack Overflow
版权声明:本文标题:javascript - using Jasmines spyon upon a private method - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736766900a1951868.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论