Node-REDの'node-red-node-test-helper'でなぜかノード取得するとnullになっちゃう時の例

Node-RED Adventcalendar　12/5担当の　ウエンツです。
最近テストコードを書いててよくハマるのでそれについて書こうと思います。

Node-REDでテストコードを書いていて、意外にハマったのが、動かすためのNodeがなぜかnullになっちゃう！！！という問題でした。

``` node.js
  it('should be loaded', function(done) {
    var flow = [{ id: 'n1', type: 'hoge', name: 'hoo' }]
    helper.load(hogeNode, flow, function() {
      var n1 = helper.getNode('n1') // ここがnullになっちゃう！！
      n1.should.have.property('name', 'hoo')
      done()
    })
  })
```

今までテストを書いていてハマったポイントは２つあったので、それをお伝えしようと思います。

# その１　本体コード・テストコードが間違ってる
まずはここを疑う必要があります。
本体コードを動かしている時にエラーが出てもそのエラー内容はテスト実行時には出してくれません。そこがかなりのハマりポイントになる。

上のテストコードは、ただノードを置いてエラーにならないか？というテストですが、`flow`に入れたフローズ構造に必須項目が漏れてたからエラーになってたと かいうことが発生しているとかになるとnullになってしまいます。

## テストコードの間違いの例
``` node.js
  it('should be loaded', function(done) {
    var flow = [{ id: 'n1', type: 'hoge', hissu: 'hisssu', name: 'hoo' }] // ここに必須項目入れなきゃいけなかったけどなかった！！！
    helper.load(hogeNode, flow, function() {
      var n1 = helper.getNode('n1')
      n1.should.have.property('name', 'hoo')
      done()
    })
  })
```

## 本体コードの間違い例
``` node.js

  function hogeNode(config) {
    RED.nodes.createNode(this, config)

    if (!config.hissu) {
      this.error('No device specified')
      return // ここのリターン書いてなかった！！！
    }

```


なのでnullになる時はまず、必須項目が入っているか？Defaultは設定してあるか？エラーが起きた時はきちんと'return'しているか？などを疑ってみると改善が見込めます。

# その２　Credentialの使い方が間違ってる

Credentialの使い方は公式にいまいち詳しく書いていないのでハマることも多いかと思います。
Credentialを利用する場合は、flowにそのcredentialを記述し、credentialを作成し、helper.loadでそのcredentialを定義しているノードを渡してあげる必要があります。
文字で書いててもよくわかんないので、コードを以下に示します。

``` node.js

const credentialNode = require('../credential') // これが必要！
const hogeNode = require('../hoge')

・・・

  credential = {
    'fc7980bd.49f74': { // 以下に出てくるflow内のcredentialノードのIDと名前を合わせる
      id: 'username',
      password: 'password'
    }
  }

    it('Success', function(done) {
      var flow = [
        {
          id: 'b962aadc.99ef58',
          type: 'hoge',
          z: '2ca93200.9acbde',
          name: 'hoge node',
          login: 'fc7980bd.49f74', // ここ必須
          x: 280,
          y: 160,
          wires: [['h1']]
        },
        {
          id: 'h1',
          type: 'helper'
        },
        {
          id: 'fc7980bd.49f74', // ここのノードが大事。上のノードで定義したIDを同じものにする
          type: 'credentials',
          z: ''
        }
      ]

      helper.load([credentialNode, hogeNode], flow, n1_credential, function() { // credentialノードと本体ノードをどちらも渡す！
        var helper_node = helper.getNode('h1')

        helper_node.on('input', function(msg) {
          try {
            expect(msg)
              .to.be.an('object')
              .with.any.keys('payload')
              .and.property('payload')
            done()
          } catch (err) {
            done(err)
          }
        })
      })
    })

```

ポイントは`hepler.node`で`credentialNode`もarrayで渡す必要があるということです。
ドキュメント（ https://github.com/node-red/node-red-node-test-helper#loadtestnode-testflows-testcredentials-cb ）に、`testCredentials`があるので、「ここでとりあえず渡せばいいのかなー」とおもって情報だけ渡しても動いてくれない点です。
きっちりルールになっているので、IDを合わせて、requireした物も一緒に渡し、flowにも含めてあげなければいけません。

# 知っとくと便利

フローをいちいちテストで手書きするのは面倒ですよね。
そういう時は、実際にNode-RED上でフローを作って、それをエクスポートしたものを貼り付けて不要なものを消す、などとすればミスが減らせます。
<img width="713" alt="スクリーンショット 2019-11-27 15.17.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23230/9c795328-c3c1-65d7-1e2f-5fa97fbd2d47.png">

# おわりに
これ以外でも多分色々と問題は起きると思いますが、まだNode-REDのテストの情報はとても少ないです！
これがみなさんんお役に立つことを望むと共に、みなさんのナレッジが今後も増えていくと嬉しいなあ。