Search code examples
angularpostangular2-servicesmockwebserver

How to mock backend data in Angular2


I have been trying to post mock data using Angular2. I have tried the following links today but I was not successful.

https://www.beyondjava.net/blog/mocking-http-services-with-angular-generically/


Below links are good but I could not make use of it

https://github.com/cornflourblue/angular2-registration-login-example/blob/master/app/_helpers/fake-backend.ts

http://embed.plnkr.co/9luTng/?show=preview

In the above link there is fake-backend.ts file as in app/_helpers/fake-backend.ts

the fake-backend I have included as in app.module.ts but how to use it?

So I want to SignUp using data request data like below:-

{
  "username": "string",
  "firstname": "string",
  "lastname": "string",
  "email": "string",
  "password": "string",
  "authtype": "plain",
  "project_license":
  "projectlicense"
}

My Response should be like below:-

{
"message": "A verification mail has been sent to your registered mail."
}

HTML Template is below:-

<div class="modal fade" id="signup-modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" style="display: none;">
      <div class="modal-dialog">
      <div class="loginmodal-container">
        <div class="row">
          <h1>Sign Up</h1><br>

          <form [formGroup]="signUpForm" (ngSubmit)="onSubmit()">
            <div class="col-md-6" id="firstname">
               <input type="text" name="firstname" placeholder="First Name" formControlName="firstname">
            </div>
            <div class="col-md-6" id="lastname">
                <input type="text" name="lastname" placeholder="Last Name" formControlName="lastname">
            </div>

            <input type="text" name="user" placeholder="Enter Username" formControlName="username">
            <input type="password" name="pass" placeholder="Password" formControlName="password">
            <input type="text" name="email" placeholder="Email Address" formControlName="email">
            <input type="text" name="license" placeholder="Project License Key" formControlName="license">

            <input logOnClick type="submit" name="login" class="login loginmodal-submit" value="Create An Account">
          </form>

          <div class="login-help">
            <p>
              By clicking Create Account you agree to our terms of services & policies.
            </p>
          </div>
         </div>
      </div>
    </div>
</div>

import { Component, ReflectiveInjector } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
import { UserService } from '../services/user.service';
import { AlertService } from '../services/alert.service';
import { Http, BaseRequestOptions, Response, ResponseOptions, RequestMethod, XHRBackend, RequestOptions, ConnectionBackend, Headers } from '@angular/http';
import { MockBackend, MockConnection } from '@angular/http/testing';
import { async, fakeAsync, tick } from '@angular/core/testing';

import { fakeBackendFactory } from '../helpers/fake-backend';

@Component({
  selector: 'sign-up',
  templateUrl: './signup.component.html',
  styleUrls: ['./signup.component.css']
})
export class SignUpComponent {
    loading = false;

    constructor(
        private userService: UserService,
        private alertService: AlertService) { }

    signUpForm = new FormGroup({
      firstname: new FormControl('Lexo', Validators.required),
      lastname: new FormControl('Luthor', Validators.required),
      username: new FormControl('lex', Validators.required),
      password: new FormControl('batman123', Validators.required),
      email: new FormControl('[email protected]', Validators.required),
      license: new FormControl('xyz', Validators.required)
    })

    // injector = ReflectiveInjector.resolveAndCreate([
    //       {provide: ConnectionBackend, useClass: MockBackend},
    //       {provide: RequestOptions, useClass: BaseRequestOptions},
    //       Http,
    //       UserService,
    // ]);

    //_userService = this.injector.get(UserService);
    //backend:MockBackend = this.injector.get(ConnectionBackend) as MockBackend;
    //backend.connections.subscribe((connection: any) => this.lastConnection = connection);

    onSubmit(){
      console.log("Form value", this.signUpForm.value);

      this.loading = true;
      this.userService.create(this.signUpForm.value).
           subscribe(
                data => {
                    console.log(data);
                    alert("")
                },
                error => {
                    this.alertService.error(error.body);
                    this.loading = false;
      });

      let myModal:HTMLElement = document.getElementById("signup-modal");
      myModal.classList.toggle("in");
      myModal.style.display = "none";
    }
}

My SignUp Service is like below:-

I do not want to store anything in localStorage but just to have a response on signup like above response.

import { Injectable, ReflectiveInjector } from '@angular/core';
import { User } from '../models/user';
import { Http, BaseRequestOptions, Response, ResponseOptions, RequestMethod, XHRBackend, RequestOptions, ConnectionBackend, Headers } from '@angular/http';
import { MockBackend, MockConnection } from '@angular/http/testing';
import {async, fakeAsync, tick} from '@angular/core/testing';

@Injectable()
export class UserService {
    connection: MockConnection;
    users = localStorage.getItem("users");

    constructor(private http: Http) { }

    create(userInput: User) {
        let users = JSON.parse(localStorage.getItem('users'));

        console.log("users", users);
        console.log("userinput" ,userInput);

        userInput.authtype = "authtype";
        userInput.project_license = "projectlicense";

        let arrayOfUsers = [];
        arrayOfUsers.push(userInput);

        if(users == null || users == undefined) {
            localStorage.setItem('users', JSON.stringify(arrayOfUsers));
        }else {
          users.push(userInput);
          localStorage.setItem('users', JSON.stringify(users));
        }

        return this.http.post('/api/users', userInput, this.jwt()).map((response: Response) => response.json());

    }

     // private helper methods

    private jwt() {
        // create authorization header with jwt token
        let currentUser = JSON.parse(localStorage.getItem('currentUser'));
        if (currentUser && currentUser.token) {
            let headers = new Headers({ 'Authorization': 'Bearer ' + currentUser.token });
            return new RequestOptions({ headers: headers });
        }
    }
}


Solution

  • There is a spyon mechanism available in angular and you can use that.

    Below are the steps you need to follow to mock them.

    inject the service, component, directive to the test bed of angular test.

      beforeEach(async(() => {
        TestBed.configureTestingModule({
          imports: [
            HttpModule,
            ReactiveFormsModule
          ],
          declarations: [
            SomeComponent,
            GenericViewComponent
          ],
          providers: [
            SomeService,  // --> this service will be mocked by spyon
          ]
        })
          .compileComponents();
      }));
    
      beforeEach(() => {
        fixture = TestBed.createComponent(SomeComponent);
        component = fixture.componentInstance;
      });
    

    Now as your SomeService in injected to your test bed, you can mock that service in another before each

    let someServiceApi = fixture.debugElement.injector.get(SomeService);
    spyOn(someServiceApi, 'methodtomockfrom-someservice')
      .and.returnValue(Observable.of({status: 'okey'});