关于 javascript:Controllers <-> 服务交互和单元测试:我做错了吗?

Controllers <-> Services interaction and unit-testing : Am I doing this wrong?

我正在构建一个 AngularJS 应用程序,我希望它是尊重或最佳实践。
因此,当我必须调用外部 $resource 或 $http 请求时,我会在外部服务/工厂中进行。
我的问题是我不知道将服务的返回值检索到调用控制器的最佳方法是什么。

目前,我所做的是:

  • 控制器调用服务
  • 服务执行 $http 调用并检查Promise。
  • 如果 promise 成功,Service $broadcast 一个带有返回对象的事件。
  • 控制器捕获该事件并执行操作。
  • 它工作得很好,允许我在不同的请求后使用相同的事件(例如:在讨论中,在检索所有消息并给自己发布消息后,调用相同的事件"要显示的新消息")

    .

    但我最终决定在我的应用程序中设置测试流程(迟到总比没有好),我意识到我可能做错了。

    --> 在对我的控制器进行单元测试时,我想模拟我的一些服务以返回给定的值。但是当我的控制器调用不返回任何内容的服务时(它们会触发事件),我认为检查服务"返回"值将非常困难且不自然。 (我总是可以检查服务是否已被调用,但不能检查结果)。

    .

    你的意见,我犯了误解错误吗?我考虑在调用服务时将Promise直接放入控制器中,这是一种好的(更好的?)方法吗?

    我知道每个应用程序都有自己的逻辑,但我认为在 AngularJS 中,"工作"逻辑(保持模块化和可测试性)的数量特别受限于某些选择和最佳实践。

    任何建议都将不胜感激。


    没有看到你的代码,我就有了我的想法:

    您的控制器可以收到该Promise并做它需要做的事情。没有真正需要广播任何东西。您的服务调用 $http 然后返回Promise。当 $http Promise被解决时,你的控制器就会知道并且可以做你需要做的事情。

    在不返回任何内容的服务中测试函数不是问题,这就是 spyOn 的问题。您可以检查该函数是否已被调用,这对于您的控制器来说应该足够了。您实际上并不关心服务中发生了什么,您关心的是您的控制器(当然是在测试控制器中)。


    请不要将事件用于此类交互。它们在代码内部弄得一团糟,降低了可维护性。有时您可以使用它们,但仅适用于某些操作和某些特定情况。使用 Promise 是一个好方法。

    这里有三个不同的选项:

    • 只需返回 $http Promise对象并在控制器内部处理它
    • 用 $q 服务做出你自己的Promise,并在其中放置你自己的逻辑来处理来自 $http 的响应或直接返回结果(它比第一个更灵活的方法)
    • 只需将一个函数回调传递给服务,您可以在服务内部调用该回调函数将结果传递回控制器。

    但是在这些情况下你绝对不需要使用事件。

    与单元测试相关的是,您将配置 $httpBackend 服务来模拟您的查询,在这种情况下,一切都会正常工作,您可以测试任何您需要的东西 ($httpBackend)。这意味着您可以注入您的服务并且它工作正常(而不是真正的 http 调用,它将返回配置为 $httpBackend 中的响应的对象)。因此,您仍然可以测试您的控制器,而无需对您的服务进行任何复杂操作。