I have the following services:
DataService.js
app.service("DataService", [
function () {
this.getData = function () { return "original value" }
}
]);
LocationService.js
app.service("LocationService", ["DataService",
function(dataSvc) {
this.getLocationData = function () {
return dataSvc.getData();
}
}
]);
Now for testing LocationService.js, how do mock DataService inside of LocationService?
This is what I currently have for LocationService_tests.js:
describe("LocationService", function () {
var locationSvc;
beforeEach(module('myModule'));
beforeEach(inject(function (LocationService) {
locationSvc = LocationService;
}));
describe("getLocationData", function () {
it("returns the location data", function () {
var mockLocationDataValue = "mocked value";
// ???
// I want to mock dataSvc.getData within getLocationData
// so it returns "mocked value" instead of "original value"
expect(locationSvc.getLocationData()).toBe(mockLocationDataValue);
});
});
});
You could mock whole service using $provide API's service method, and change your service to returned mock data.
describe("LocationService", function () {
var locationSvc;
beforeEach(module('myModule'));
beforeEach(module(function($provide) {
$provide.service('LocationService', function() {
this.getData = function() {
return "mock value";
}
});
});
beforeEach(inject(function (LocationService) {
locationSvc = LocationService;
}));
...
});
Related
I have a function inside a controller, which calls a method of an object "mapping".
$scope.createParameter = function (parameter) {
var apiObj = {};
mapping.createApiService(apiObj)
}
that object structure is as follows, and this method 'createApiService' calls a 'create' method of apiService.
var mapping = {
createApiService : apiService.create
}
I have injected that apiService into my Testsuite. and a spyon is also been added as follows.
spyOn(apiService, "create").and.callFake(function () {
return {
then: function (callback) {
callback(createResponse);
return {
catch: function () {
}
}
}
}
but when I execute my it block with following expectation it gives an error "expected spy create to have been called.
expect(apiService.create).toHaveBeenCalled();
can some one help me with this?
EDIT: Added testing code
describe("Controller", function () {
beforeEach(angular.mock.module("ui.router"));
beforeEach(angular.mock.module("PpmApp"));
var $controller, $scope, $state, $httpBackend, parameterDetails, apiService, constantsProvider;
beforeEach(inject(function (_$controller_, _$rootScope_, _$state_, _$httpBackend_, _apiService_, _constantsProvider_) {
$controller = _$controller_;
$scope = _$rootScope_.$new();
$state = _$state_;
$scope.header = {};
$state.current = {};
$httpBackend = _$httpBackend_;
apiService = _apiService_;
constantsProvider = _constantsProvider_;
$controller = $controller("Controller", { "$scope": $scope, "parameterDetails": parameterDetails });
}));
describe("create", function () {
it("should succeed with valid Input", function () {
var parameter = {
ParameterType: 1,
ParameterId: 2,
LookupCurveStructures: [{
Name: "Parameter name",
XAxisName: "XAxisName",
YAxisName: "YAxisName",
XAxisDataType: 1,
YAxisDataType: 2
}]
};
var createResponse = {
Data: [],
IsSuccess: true,
Message: "Parameter added successfully"
};
spyOn(apiService, "create").and.callFake(function () {
return {
then: function (callback) {
callback(createResponse);
return {
catch: function () {
}
}
}
}
});
$scope.createParameter(parameter);
expect($scope.createPopupInfo.validationErrors.isError).toEqual(false);
expect(apiService.create).toHaveBeenCalled();
expect($scope.parameterDetails.Parameters).toEqual([]);
});
});
});
Given the following test.
The $provided service is not being injected. If I debug the test in karma I can see that the service being provided is the real one, and not the mock.
The really weird thing, is that if I remove the $provide.service... I get an error Error: [$injector:unpr] Unknown provider: ficaServiceProvider <- ficaService. This clearly means that the service is getting registered, just not replaced?
describe("component: FicaStatusComponent",
function () {
var fs;
beforeEach(function () {
module("aureus",
function ($provide) {
$provide.service("ficaService", function () {
this.status = function () {
return $q(function (resolve, reject) {
resolve([{ documentType: { id: 1 } }]);
});
}
})
});
});
beforeEach(inject(function (_$componentController_, _ficaService_) {
$componentController = _$componentController_;
fs = _ficaService_;
}));
it("should expose a `fica` object", function () {
console.log('should expose');
var bindings = {};
var ctrl = $componentController("ficaStatus", null, bindings);
expect(ctrl.fica).toBeDefined();
});
it("compliant with no documents should not be compliant",
function () {
var ctrl = $componentController("ficaStatus");
expect(ctrl.fica.length).toEqual(1);
});
}
);
The second test compliant with no documents... is failing.
Chrome 56.0.2924 (Windows 10 0.0.0) component: FicaStatusComponent compliant with no documents should not be compliant FAILED
Error: Unexpected request: GET api/fica/status/
I have also tried this, expecting to have an empty object injected, but the "real" service is there nevertheless?
module("aureus", function($provide) {
$provide.value("ficaService", function() { return {}; });
$provide.service("ficaService", function() { return {}; });
});
Here is the implementation of the controller for the component:
var FicaStatusController = (function () {
function FicaStatusController($log, $loc, ficaService) {
var _this = this;
this.$log = $log;
this.$loc = $loc;
this.ficaService = ficaService;
this.fica = [];
this.ficaService.status(1234).then(function (_) { return _this.fica = _; });
}
FicaStatusController.$inject = ["$log", "$location", "IFicaStatusService"];
module("aureus").component("ficaStatus", new FicaStatusComponent());
module("aureus").service("IFicaStatusService", FicaStatusService);
The service is as follows:
var FicaStatusService = (function () {
function FicaStatusService($log, $http) {
this.$log = $log;
this.$http = $http;
}
FicaStatusService.prototype.status = function (accountNumber) {
var url = "api/fica/status/" + accountNumber;
this.$log.log("status: " + url);
return this.$http
.get(url)
.then(function (_) { return _.data; });
};
return FicaStatusService;
}());
...
You have added your service in your module like this:
module("aureus").service("IFicaStatusService", FicaStatusService);
That means that you will need to provide IFicaStatusService instead of ficaService with $provide.
I am having a controller like below
(function () {
var mockController = function ($scope, MockService) {
$scope.message = "This is a text message";
$scope.getCities = function () {
return MockService.getCities();
};
};
var mockService = function ($http) {
this.getCities = function () {
return $http.get("../rest/url", {
headers: {
'Accept': 'application/yang.data+json'
}
});
};
};
angular.module("MockApp", [])
.service("MockService", mockService)
.controller("MockController", mockController);
}())
I am trying to write a UT mocking the service like below
describe("MockController", function () {
var $scope;
beforeEach(function () {
module("MockApp");
inject(function (_$controller_, _$rootScope_, MockService) {
$scope = _$rootScope_.$new();
spyOn(MockService, "getCities").and.callFake(function () {
return [{
city: "Bangalore"
, country: "India"
}];
});
controller = _$controller_("MockController", {
$scope: $scope
});
});
});
describe("Test", function () {
it("Should be Bangalore", function () {
$scope.getCities()
.then(function (data) {
console.log("got it");
})
});
});
});
Its throwing an error saying
TypeError: $scope.getCities(...).then is not a function
Please help me.
I think:
$scope.getCities = function () {
return MockService.getCities();
};
should be:
$scope.getCities = function () {
return MockService(getCities());
};
I am having a controller like below
(function () {
var newPlaceController = function ($scope, PlacesService, $mdDialog) {
$scope.newPlace = {
"city": "",
"country": ""
};
$scope.addCity = function () {
$scope.places.push($scope.newPlace);
PlacesService.addCity($scope.newPlace);
$mdDialog.hide();
};
$scope.cancel = function(){
$mdDialog.hide();
};
};
angular.module("module.place")
.controller('NewPlaceController', newPlaceController);
}());
Also I have a test file like below which tests whether the initialization value of newPlace is correct.The code is like below
describe("NewPlaceController", function () {
var $scope, ctrl;
beforeEach(module("module.place"));
beforeEach(
inject(function (_$controller_) {
$scope = {};
controller = _$controller_('NewPlaceController', {
$scope: $scope
});
}));
describe("Initialization", function () {
it("asdasd", function () {
expect($scope.newPlace).toEqual({
city: ''
, country: ''
});
})
});
});
It's working fine. My doubt is how can I test the addCity and cancel functions in the controller.
You can use it like this
it("Should call addCity", function () {
var spy = spyOn(PlacesService, 'addCity');
controller.addCity();
expect(spy).toHaveBeenCalled();
})
it("Should call mdDialog hide", function () {
var spy = spyOn($mdDialog, 'hide');
controller.cancel();
expect(spy).toHaveBeenCalled();
})
function configure($provide, $injector) {
$provide.provider("testservice", function () {
this.$get = function () {
this.property = 777;
};
});
var s = $injector.get("testservice");
The last line throws this error:
Unknown provider: testservice
Why so?
To access provide in config phase, we need to append 'Provider' to the name of the provider.
module.config(function ($provide, $injector) {
$provide.provider("testservice", function () {
this.$get = function () {
this.property = 777;
};
});
var s = $injector.get("testserviceProvider");
console.log(s)
});