具有两种方式绑定的 Angular 4 单元测试形式。从视图更新模型时出现问题

2024-01-21

我偶然发现了一个奇怪的问题。我正在使用基于模板的表单和双向绑定执行单元测试。这是测试代码:

describe('Template Forms Input', () => {

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [BrowserModule, FormsModule],
      declarations: [DummyFormsComponent],
    }).compileComponents();
  });

  it('DOM input value changes the component model', fakeAsync(() => {

    const fixture = TestBed.createComponent(DummyFormsComponent);
    fixture.detectChanges();
    const dummyInputDe = fixture.debugElement.query(By.css('input'));
    const dummyInputEl = dummyInputDe.nativeElement;

    dummyInputEl.value = 'Super dummy';
    dummyInputEl.dispatchEvent(new Event('input'));

    tick();
    fixture.detectChanges();

    expect(fixture.debugElement.query(By.css('h2')).nativeElement.textContent).toEqual('Super dummy');
  }));
});

@Component({
  selector: 'dummy-forms',
  template: `
    <form>
      <input name="title" [(ngModel)]="model.anotherDummyValue">
    </form>
    <h2>{{model.anotherDummyValue}}</h2>
  `
})
class DummyFormsComponent {

  model = { anotherDummyValue: '', date: '' };
}

我无法让测试通过。 h2 始终为空。然而。如果我删除<form>标记并仅保留视图中的输入。测试正在通过。

我认为我的异步行为做错了。有人有主意吗?


遇到了和你类似的问题(请参阅下面我的 Angular 环境详细信息),搜索了所有有关单元测试的互联网NgModel。最后我发现将值单独设置为查询的输入(实际上是通过NgModel) 是不足够的。 IE。dummyInputEl.value = 'Super dummy';dispatchEvent('input')在你的情况下永远不会得到实际的NgModel操作启动并运行。

Solution

为了解决这个问题,你必须得到injected NgModel来自绑定的实例input并通过其设置值valueAccessor财产通过writeValue方法,在发出之前'input'DOM 原生元素上的事件.

...
const ngModel = dummyInputDe.injector.get(NgModel);

tick();                    // <== Important to wait until stable before writing value

ngModel.valueAccessor.writeValue('Super dummy');
dummyInputDe.nativeElement.dispatchEvent(new Event('input'));

fixture.detectChanges();                   // <= force updates to the view


expect(fixture.debugElement.query(By.css('h2'))
  .nativeElement.textContent).toEqual('Super dummy');                // <= Viola!
...

请注意,我们必须提供tick在 - 的里面fakeAsync在写信之前NgModel值访问器。可能是因为 NgModel 的访问器需要一段时间才能准备好,然后才能在其上写入值(在这方面感谢反馈).

虽然在规格没有的情况下fakeAsync区,相同的情况应该用fixture.whenStable()决心承诺得到所需的结果。


Note:关于网络上单元测试的每个主题,尤其是当NgModel是有问题的,这在任何地方都没有提到。甚至连 Angular 官方文档都没有。不确定新的 Angular 版本是否(特别是变化FormsModule执行)迫使这一改变。


角度环境设置

  • v5.2.0
  • 业力v2.0.0
  • 茉莉花(茉莉花芯)v2.8.0
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

具有两种方式绑定的 Angular 4 单元测试形式。从视图更新模型时出现问题 的相关文章

  • 如何使用 Web 套接字和 Angular CLI 设置代理

    我有一个使用 Angular CLI 构建的简单 Web 应用程序 我希望它使用网络套接字与后端通信 我已经编写了后端 并使用一个简单的 index html 页面进行了测试 服务器可以在套接字上发送和接收该页面 在我的 angular c
  • Angular 中的文件输入事件类型

    所以我已经使用 Angular 和 Typescript 很长时间了 我似乎无法找出输入文件的类型是什么 例如
  • 单击上一页的按钮路由到该页面后如何刷新页面

    我有 2 个页面 一个主页和一个页面 2 当我单击主页上的按钮时 它会路由到 page2 现在 单击主页上的按钮后 当我到达第 2 页时 它应该刷新 因为我的项目中存在一些缓存问题 我在ngoninit上添加了window location
  • 包含routeChangeSuccess的AngularJS测试控制器

    我正在尝试创建单元测试来测试导航列表控制器 但在创建测试时遇到问题 这是控制器的代码 navListModule controller NavListCtrl scope NavList function scope NavList sco
  • 如何在Angular2中正确使用依赖注入(DI)?

    我一直在试图弄清楚 DI 依赖注入在 Angular2 中是如何工作的 每次当我尝试将服务 或类注入我的组件时 我都会遇到很多问题 从不同的谷歌搜索文章中 我需要使用providers 在组件配置中 或者有时我需要使用 Inject 在我的
  • Angular 2 runOutsideAngular 仍然改变 UI

    从我的理解来看runOutsideAngular https angular io docs ts latest api core index NgZone class html runOutsideAngular anchor 如果我需要
  • 如何在 Angular @Input 中仅接受预定义值

    我的问题是 我在 a 中收到一个字符串值作为组件的参数 但我想限制可以用作参数的值 就像enum I use Input type string 但是在组件中 一切都可以引入type正如我之前所说 我需要将其限制为 3 个选项 例如Enum
  • Rxjs、fromEvent处理多个事件

    在 rxjs 5 1 中处理同一 DOM 节点上的多个事件的最佳方法是什么 fromEvent element event name 但我一次只能指定一个事件 我要手柄scroll wheel touchmove touchend even
  • Angular4 屏蔽输入中的字符而不更改其值

    如何屏蔽输入中除 Angular 4 中最后四个字符之外的所有字符 即显示 而不更改实际值 例如 输入文本框中的数字应类似于 1234 且值应为 7671234 使用指令 Directive selector stringHide expo
  • 使用覆盖率信息测试 Go 中的 os.Exit 场景 (coveralls.io/Goveralls)

    这个问题 如何在 Go 中测试 os exit 场景 https stackoverflow com questions 26225513 how to test os exit scenarios in go 以及其中得票最高的答案 列出
  • 在哪里存储角度中的 JWT 令牌?

    我正在使用 Django 和 Angular 构建一个应用程序 目前 我正在本地存储上存储后端发出的 JWT 但是 我担心 XSS 攻击 我应该使用仅 HTTP 的 cookie 来存储令牌吗 我还考虑将令牌存储在我的身份验证服务类中的变量
  • Node.js 中的异步或步骤

    我无法让我的异步代码与 node js 一起使用 尝试异步和步骤库 代码仅返回第一个函数 似乎没有执行其余函数 我究竟做错了什么 thanks var step require step step function f1 console l
  • 订阅内循环订阅?

    我目前正在与订阅内的 multiples forEach 订阅作斗争 我正在尝试检索对象列表 然后通过它们的 ID 检索它们的图像 目前我已经这样做了 this appTypeService get pipe map apps AppTyp
  • 在 Angular 5 中,如何从父组件访问动态添加的子组件?

    我正在开发一个 Ionic Angular 5 项目 我需要动态加载一些组件 继动态组件加载器示例 https angular io guide dynamic component loader在 Angular 文档中 我能够成功加载组件
  • 从文件夹中删除文件的单元测试方法

    我们有一个方法 它将文件夹名称和天数作为参数 public void Delete string folder int days var files Directory GetFiles folder foreach var file in
  • Angular 2 和 TypeScript 的承诺

    我正在尝试使用routerCanDeactivate我的应用程序中的组件的函数 简单的使用方法如下 routerCanDeactivate return confirm Are you sure you want to leave this
  • Coffeescript + 单元测试:全局变量?

    我正在尝试使用 Jasmine 对用 CoffeeScript 编写的小型应用程序进行单元测试 我发现很多资料都说单元测试可以在从 CoffeeScript 编译的 JS 上完美地完成 如果所有内容都包装在匿名函数中以避免污染名称空间 如何
  • 从Web API同步调用外部api

    我需要从我的 Web API 2 控制器调用外部 api 类似于此处的要求 使用 HttpClient 从 Web API 操作调用外部 HTTP 服务 https stackoverflow com questions 13222998
  • 混合 ExecutionContext.SuppressFlow 和任务时 AsyncLocal.Value 出现意外值

    在应用程序中 由于 AsyncLocal 的错误 意外值 我遇到了奇怪的行为 尽管我抑制了执行上下文的流程 但 AsyncLocal Value 属性有时不会在新生成的任务的执行范围内重置 下面我创建了一个最小的可重现示例来演示该问题 pr
  • 如何使用 Angular CLI 在特定文件夹中生成组件?

    我将 Angular 4 与 Angular CLI 结合使用 并且可以使用以下命令创建一个新组件 E HiddenWords gt ng generate component plainsight 但我需要在 plainsight 中生成

随机推荐