mmag

ハマったことメモなど

AngularのHttpを使うサービスの単体テスト

4系の話。Httpを使ってAPIアクセスするようなサービス(ここではPostService)のテスト。もう一度同じものを書けと言われても無理だなと思ったので書いておく。

import { TestBed, inject, async } from '@angular/core/testing';
import { MockBackend, MockConnection } from '@angular/http/testing';
import {
  Http, Response, RequestMethod, ConnectionBackend,
  RequestOptions, BaseRequestOptions, ResponseOptions
} from '@angular/http';

import { PostService, Post } from './post.service';

describe('PostService', () => {
  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [
        {provide: ConnectionBackend, useClass: MockBackend},
        {provide: RequestOptions, useClass: BaseRequestOptions},
        Http,
        PostService
      ]
    });
  });

  describe('fetchAll', () => {
    beforeEach(inject([ConnectionBackend], (mockBackend: MockBackend) => {
      mockBackend.connections.subscribe((connection: MockConnection) => {
        expect(connection.request.method).toEqual(RequestMethod.Get);

        connection.mockRespond(new Response(new ResponseOptions({
          status: 200,
          body: {
            posts: [{content: "Hello"}, {content: "Goodbye"}]
          }
        })));
      });
    }));

    it('should return list of posts', async(inject([PostService], (service: PostService) => {
      service.fetchAll().subscribe((posts: Post[]) => {
        expect(posts[0].body).toEqual("Hello");
        expect(posts[1].body).toEqual("Goodbye");
      });
    })));
  });
});

テストコード中で投げたリクエストが、ConnectionBackenduseClassに設定したMockBackendconnectionsに流れてくるので、それに対する応答をbeforeEachで設定している。リアクティブ。

あとはsubscribeの中でexpectすることになるので、itの第2引数をasyncで包むとこが忘れがちポイント。

Testing Angular 2 Services and Http with Jasmine などを参考にしました。

ReDocに食わせるOpenAPIにはoperationIdを書こう

最近ReDocを触っていてヤヤハマリに遭遇することがあるので書いておきます。

github.com

operationIdってなにさというと、OpenAPIのOperation Objectの一項目で、操作を識別するための一意な文字列のことです。ReDocに食わせるOpenAPIには、と書きましたが、そうでなくても書いておくべきやつです。

困ったこと

v1.14.0の話です。

ReDocのデモを見るとわかりますが、例えばaddPetというoperationIdが付いた操作には、パーマリンクとして http://rebilly.github.io/ReDoc/#operation/addPet が与えられます。operationIdをちゃんと書いたときはいいのですが、ここをサボると、ReDocは他の情報から頑張って一意な文字列を作ろうとします。健気なやつです。ただその文字列が、

/#null%2Fpaths%2F~1v1~1pet.json%2Fget

みたいな。せっかく頑張ってくれたんですが、ちょっと積極的に使う気になれない。しかも場所によって先頭のnullundefinedになってリンクとして機能しないっていう…。ということで、operationIdはサボらずちゃんと書きましょう。

minikubeを触った

ふとkubernetesを触ってみようと思い、ローカルで試すにはminikubeがよいということで試してみた。一通りチュートリアルをやってわかった気になったので、ちょっとした構成をつくってみたのがこちら。

github.com

docker hubに上げてないイメージを使うために

$ minikube start
$ eval $(minikube docker-env)

とかしないといけないはず。これをした上で、

$ ./build.sh

とすると、docker buildやらDeploymentの作成が行われ、以下が2組立ち上がる。

  • 80番を3000番にリバースプロキシするnginx
  • 今の時刻を文字で返すWebアプリ
$ ./build.sh
Sending build context to Docker daemon  5.718MB
Step 1 : FROM golang:alpine
 ---> c82f63bb2928
Step 2 : ADD . /tmp
 ---> Using cache
 ---> be2da95d39d6
Step 3 : WORKDIR /tmp
 ---> Using cache
 ---> 153c17f1ff46
Step 4 : RUN go build -o /opt/app app.go
 ---> Using cache
 ---> d70e89cd9650
Step 5 : ENTRYPOINT /opt/app
 ---> Using cache
 ---> f48256763296
Successfully built f48256763296
Sending build context to Docker daemon  3.584kB
Step 1 : FROM nginx:latest
 ---> 5766334bdaa0
Step 2 : COPY ./nginx.conf /etc/nginx/
 ---> Using cache
 ---> d71e8a6ed75d
Successfully built d71e8a6ed75d
deployment "current-time" created
service "current-time" exposed
open 192.168.99.100:31744

最後に出力されているURLへ行くと、"2017-04-23 08:11:50.512403779 +0000 UTC"という感じが見えて、動いていることが確認できる。