在私有方法上使用 Jasmine spyon
Posted
技术标签:
【中文标题】在私有方法上使用 Jasmine spyon【英文标题】:using Jasmines spyon upon a private method 【发布时间】:2012-01-18 12:29:44 【问题描述】:是否可以在类私有方法上使用 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();
);
);
【问题讨论】:
【参考方案1】:spyOn(fakePerson, <never>'sayHello');
spyOn(fakePerson, <keyof Person>'sayHello');
既能消除类型错误,又不会干扰 TSLint 的 no-any
规则。
【讨论】:
【参考方案2】:const spy = spyOn<any>(component, 'privateMethod');
expect(spy).toHaveBeenCalled();
为避免有关通过字符串文字访问对象的 lint 警告,请创建 spy 对象的本地常量。
【讨论】:
【参考方案3】:spyOn<any>(fakePerson, 'sayHello');
expect(fakePerson['sayHello']).toHaveBeenCalled();
通过将<any>
添加到 spyOn,您可以将其从 typescript 类型检查中删除。
您还需要使用数组索引符号来访问测试中的私有方法(sayHello)期望
【讨论】:
虽然此代码可能会回答问题,但提供有关它如何和/或为什么解决问题的额外上下文将提高答案的长期价值。【参考方案4】:假设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');
使用 any
创建私有方法的间谍。
要访问私有(或受保护)方法,请使用 []
运算符。
【讨论】:
投了反对票,因为您没有解决主要问题,即您如何监视私有方法。此代码与问题中最初提供的代码并没有什么不同。 @JeffryHousersayHello
是私有方法。第一行是如何在上面创建一个间谍。第二行是测试。
知道了;您的答案缺少有关如何使用 <any>
标签监视私有方法的说明。这就是我感到困惑的原因。【参考方案5】:
Typescript 被编译成 javascript,并且在 javascript 中每个方法都是公开的。所以你可以使用数组索引符号来访问私有方法或文件,即:
Object['private_field']
【讨论】:
博客链接不幸失效了。 这里投了反对票,部分用于死博客链接;部分原因是我们不能使用对象数组表示法来设置间谍。【参考方案6】:如果您将 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();
);
);
【讨论】:
如果我尝试调用非导出(私有)函数,则会出现类型错误:Error:(33, 56) TS2345:Argument of type '"sayHello"' is not assignable to parameter of type '"sayGoodbye"'.
其中sayGoodbye
是Person
上的公共方法,sayGoodbye
是私有方法。我必须将它转换为任何(“sayHello” as any)
我在这里需要更多上下文,您的任务似乎不起作用并且无法访问私有函数。但请尝试像这样访问它:person["sayHello"]
而不是 person.sayHello
(如果您正在这样做)。这不是最佳做法,但在极少数情况下可以原谅 ;)
同意@FlavorScape。 Typescript(至少 1.7 及更高版本)期望被监视的函数是公共的,并且由于 sayHello 不是类型 sayGoodbye(或任何其他公共函数),它会抛出错误。我只能使用上面列出的 spy 来解决这个问题。
自从我上次发表评论以来,情况似乎发生了变化。 spy<any>
可能确实是正确的答案。谢谢
spy<any>
是一个启示。【参考方案7】:
就我而言(打字稿):
jest.spyOn<any, string>(authService, 'isTokenActual')
OR 模拟结果:
jest.spyOn<any, string>(authService, 'isTokenActual').mockImplementation(() =>
return false;
);
【讨论】:
【参考方案8】:只需在 spyon() 函数中添加一个通用参数 :
spyOn<any>(fakePerson, 'sayHello');
完美运行!
【讨论】:
我试过这个解决方案,效果很好。此外,可以使用数组索引表示法访问私有字段,就像我之前提到的那样。 这些都不适合我。您不能通过数组表示法访问,因为 spyOn 需要两个参数。如图所示放置 也会引发错误数量的参数错误。这对我有用:spyOn(fakePerson as any, 'sayHello');
我也这样做。有没有更好的方法而不使用任何“通用”?我试过例如 spyOn<any>
究竟做了什么才能使它起作用?
@risingTide 添加<any>
会删除类型检查,因此不会出现 TypeScript 编译时错误(编辑器中也不会出现错误)。但是 TypeSciprt 最终会被编译成每个方法都是公开的 Javascript,因此这将有助于消除 Typescript 错误。【参考方案9】:
如果您想在一个类中测试私有函数,为什么不向您的类添加一个构造函数来指示这些私有函数被返回?
请仔细阅读以了解我的意思:http://iainjmitchell.com/blog/?p=255
我一直在使用类似的想法,到目前为止效果很好!
【讨论】:
如果你发布了你的私有方法,它就不再是私有了。顺便说一句,正如我在回答中所描述的,测试 privat 方法没有多大意义。 我们可以同意是不同意的。我们的 javascript 代码库非常庞大,我们只在某些类上公开了一些公共函数/属性。在这些私有函数中处理了很多逻辑。我只公开了一个私有方法,因此测试框架可以访问它。如果没有正确调用构造函数,则不会返回私有函数。【参考方案10】:没有因为您无法访问实例上下文之外的私有函数。
顺便说一句,监视您要测试的对象不是一个好主意。当您测试是否调用了您要测试的类中的特定方法时,它什么也没说。假设您编写了测试并通过了测试,两周后您重构了函数中的一些内容并添加了一个错误。所以你的测试仍然是绿色的,因为你调用了这个函数。乙
当您使用Dependency Injection 时,间谍很有用,其中所有外部依赖项都由构造函数传递,而不是在您的类中创建。因此,假设您有一个需要 dom 元素的类。通常,您将在类中使用 jquery 选择器来获取此元素。但是您想如何测试是否使用该元素完成了某些操作?当然,您可以将其添加到您的测试页面 html 中。但是您也可以在构造函数中调用传递元素的类。这样做,您可以使用 spy 来检查您的类是否按预期与该元素交互。
【讨论】:
说“监视你想测试的对象不是一个好主意”是不正确的。间谍的使用不仅限于检查一个函数是否被简单地调用,仅此而已。您可以使用间谍检查返回值,完全替换测试用例的函数,抛出错误等。我建议阅读 jasmine 文档以获得更完整的理解。 窥探不是个好主意!??你不能再错了!是的,我同意蒂姆的观点,你应该看看 doco,谁投了这个票?! 我不是这么说的。可以使用间谍。但是您应该将要测试的对象作为黑匣子处理。只测试进出的东西。不要测试黑匣子的内部,如果你监视被测对象的方法,你会怎么做。所以监视你传递给对象的回调是完全没问题的。 恰恰相反。您正在测试“单元”,您对其他“单元”在做什么不感兴趣。您将对其他“单元”进行测试。以上是关于在私有方法上使用 Jasmine spyon的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Jasmine 为私有方法编写 Angular / TypeScript 单元测试
使用 Jasmine 对包含私有超时的单元测试 Angularjs 指令