使用Jasmines spyon的私有方法

use*_*014 43 javascript unit-testing jasmine

是否可以在类私有方法上使用Jasmine单元测试框架的spyon方法?

文档给出了这个例子,但这可以灵活用于私有函数吗?

describe("Person", function() {
    it("calls the sayHello() function", function() {
        var fakePerson = new Person();
        spyOn(fakePerson, "sayHello");
        fakePerson.helloSomeone("world");
        expect(fakePerson.sayHello).toHaveBeenCalled();
    });
});
Run Code Online (Sandbox Code Playgroud)

提前致谢

Lui*_*yfe 90

只需在spyon()函数中添加一个通用参数<any>:

 spyOn<any>(fakePerson, 'sayHello');
Run Code Online (Sandbox Code Playgroud)

它完美地工作!

  • @risingTide添加&lt;any&gt;会丢弃类型检查,因此不会出现TypeScript编译时错误(并且编辑器中也不会出现错误)。但是TypeSciprt最终会被编译成Javascript,其中每个方法都是公共的,因此这将有助于消除Typescript错误。 (5认同)
  • 我试过这个解决方案,效果非常好.另外,可以使用数组索引表示法访问私有字段,就像我之前提到的那样. (3认同)
  • 这些都不适合我。由于spyOn带有两个参数,因此无法通过数组表示法进行访问。如图所示放置&lt;any&gt;也会引发错误的参数数量错误。这对我有用:`spyOn(fakePerson as any,'sayHello');` (3认同)
  • 我也这样做。有没有更好的方法而不会被任何人如此“通用”?我尝试了例如spyOn &lt;fakePerson&gt;(fakePerson,'sayHello'); 但随后仍然抱怨“打招呼”。是否可能像spyOn &lt;fakePerson&gt; &lt;fuction&gt;之类的东西?对于更好的上下文? (2认同)
  • 有人还能解释为什么这种解决方案有效吗?到底添加`&lt;any&gt;`到底能做什么呢? (2认同)

ome*_*mer 20

spyOn<any>(fakePerson, 'sayHello');
expect(fakePerson['sayHello']).toHaveBeenCalled();
Run Code Online (Sandbox Code Playgroud)

通过添加<any>到 spyOn,您可以将其从打字稿类型检查中删除。您还需要使用数组索引符号来访问测试中的私有方法(sayHello)


A-S*_*ani 16

假设sayHello(text: string)是一个私有方法。您可以使用以下代码:

// 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');
Run Code Online (Sandbox Code Playgroud)
  • 使用any.
  • 要访问私有(或受保护)方法,请使用[]运算符。


mln*_*drv 8

spyOn(fakePerson, <never>'sayHello');
Run Code Online (Sandbox Code Playgroud)
spyOn(fakePerson, <keyof Person>'sayHello');
Run Code Online (Sandbox Code Playgroud)

两者都会消除类型错误并且不会干扰 TSLint 的no-any规则。


jur*_*url 7

如果您为对象使用 Typescript,则该功能并不是真正私有的。
您只需要保存从spyOn调用返回的值,然后查询它的calls属性。

最后这段代码应该适合你(至少它对我有用):

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();
    });
});
Run Code Online (Sandbox Code Playgroud)

  • 如果我尝试调用非导出(私有)函数,我会收到类型错误:`Error:(33, 56) TS2345:Argument of type '"sayHello"' 不可分配给类型 '"sayGoodbye"' 的参数。 ` 其中`sayGoodbye` 是`Person` 的公共方法,`sayGoodbye` 是私有的。我必须将它转换为任何(“sayHello”) (4认同)

小智 5

就我而言(打字稿):

jest.spyOn<any, string>(authService, 'isTokenActual')
Run Code Online (Sandbox Code Playgroud)

或模拟结果:

jest.spyOn<any, string>(authService, 'isTokenActual').mockImplementation(() => {
  return false;
});
Run Code Online (Sandbox Code Playgroud)


And*_*rle -2

没有原因,您无法访问实例上下文之外的私有函数。

顺便说一句,监视你想要测试的对象并不是一个好主意。当您测试您想要测试的类中是否调用了特定方法时,它什么也没说。假设您编写了测试并通过了,两周后您重构了函数中的一些内容并添加了一个错误。所以你的测试仍然是绿色的,因为你调用了函数。乙

当您使用依赖注入时,间谍非常有用,其中所有外部依赖项都由构造函数传递,而不是在您的类中创建。假设您有一个需要 dom 元素的类。通常,您会在类中使用 jquery 选择器来获取此元素。但是你想如何测试该元素是否完成了某些操作呢?当然你可以将它添加到你的测试页面 html 中。但您也可以在构造函数中传递元素来调用您的类。这样做,您可以使用间谍来检查您的类是否按照您的预期与该元素交互。

  • 说“监视你想要测试的对象不是一个好主意”是不正确的。间谍的使用不仅限于检查函数是否被简单调用,仅此而已。您可以使用 spies 检查返回值、完全替换测试用例的函数、抛出错误等。我建议阅读 jasmine 文档以获得更完整的理解。 (31认同)
  • 我不是这么说的。使用间谍是可以的。但你应该将你想要测试的对象作为黑匣子来处理。仅测试进出的内容。不要测试黑匣子的内部结构,如果你监视被测对象的方法,你会做什么。因此监视您传递给对象的回调是完全没问题的。 (3认同)
  • 监视不是一个好主意!你大错特错了!是的,我同意蒂姆的观点,你应该看看 doco,谁投了这个票?! (2认同)