I'm using ROS service server in python:
#! /usr/bin/env python3
import rospy
from std_srvs.srv import SetBool, SetBoolResponse
class StateController:
def __init__(self):
rospy.init_node("state_controller", anonymous=True)
rospy.Service("validate_vision_info", SetBool, self.validVision)
rospy.spin()
def validVision(self, req):
model_valid = req.data
rospy.logwarn("Vision Model Validation: {}".format(req.data))
return SetBoolResponse(success=True, message="")
if __name__ == "__main__":
try:
controller_ = StateController()
except rospy.ROSInterruptException:
logging.error("Error in the State Controller")
And I'm calling that service from a javaScript server client as follows:
import { Ros, Service, ServiceRequest } from "roslib";
class ROSInterface {
constructor() {
this.ros = new Ros({
url: "ws://localhost:9090",
});
}
createService = (service_name, service_type) => {
let service = new Service({
ros: this.ros,
name: service_name,
serviceType: service_type,
});
return service;
};
requestService = (params) => {
let request = new ServiceRequest(params);
return request;
};
callService_ = (service_name, service_type, params) => {
return new Promise((resolve, reject) => {
const srv = this.createService(service_name, service_type);
const req = this.requestService(params);
srv.callService(
req,
(result) => {
console.log(result);
resolve(result);
},
(error) => {
console.log(error);
reject(error);
}
);
});
};
}
async function validate(val) {
const service_name = "/validate_vision_info";
const service_type = "std_srvs/SetBool";
console.log(val);
const iface_ = new ROSInterface();
let serv = await iface_
.callService_(service_name, service_type, val)
.then((result) => {
return result;
}).catch(e => {
console.log(e);
});
console.log("service result", serv);
}
validate(true);
validate(false);
In both service calls I get False in the Service Service Request in the Python code.
Can you please tell me how to solve it? thanks in advance.
As I'm using VueJS3, I had to use State Management with Reactivity: variables stored in store.js.
The message (params) has to be passed in the format {data: store.variable} to conform with the service setBool description
Related
I'm new in Jest and don't understand how to mock request to service for unit test.
EmployeeController.js
const EmployeeService = require('../services/employeeService');
exports.getEmployeeById = (req, res) => {
EmployeeService.find(req.params.employeeId) // need to be mocked
.then((employee) => {
if (employee == 0 || '') {
return res.status(404).json({
success: false,
message: 'Employee not found!'
});
} else {
return res.status(200).json({
success: true,
employee: employee
});
}
}).catch(err => {
res.status(404).json({
success: false,
message: 'Employee not found!'
});
});
}
EmployeeService.find - returns to me from the database the employee object by the entered Id in url.
EmployeeService.js
const sql = require('../config/connection');
const Promise = require('bluebird');
const connection = require('../config/connection');
const Employee = require('../models/employee.model');
var queryAsync = Promise.promisify(connection.query.bind(connection));
Employee.find = async function (employeeId) {
var result = queryAsync(
"SELECT empID, empName, IF(empActive, 'Yes', 'No') empActive, dpName FROM Employee INNER JOIN Department ON empDepartment = dpID WHERE empID = ? ", employeeId);
return result;
}
employee.model.js - model of employee.
const Employee = function (emp) {
this.empName = emp.empName;
this.empActive = emp.empActive;
this.empDepartment = emp.empDepartment;
this.creator = emp.creator;
};
module.exports = Employee;
Jest has built in utilities for stubbing out dependencies.
const employeeService = require("../services/employeeService");
const employeeController = require("./employeeController");
describe("employeeController", () => {
beforeEach(() => {
// this mock can be overridden wherever necessary, eg by using
// employeeService.find.mockRejectedValue(new Error("oh no"));
// by default, resolve with something that meets the needs of your consuming
// code and fits the contract of the stubbed function
jest.spyOn(employeeService, "find").mockResolvedValue(someMockQueryResult);
});
afterEach(() => {
jest.restoreAllMocks();
});
// contrived test to show how jest stubs can be used
it("fetches the employee", async () => {
await employeeController.getEmployeeById(123);
expect(employeeService.find).toHaveBeenCalledWith(123);
});
});
There are also options for mocking out the entire module. Check out the jest docs:
https://jestjs.io/docs/en/mock-functions.html
https://jestjs.io/docs/en/manual-mocks.html
I am trying to display data in my Angular frontend that is called against an Oracle DB linked to my Node backend. Currently if I go to the phsyiscal API link I will see the data and it will display in my backend console.log.
Am I missing something easy here? I am a newbie so apologize in advance if this is easy.
Angular Page Component
import { Component, OnInit } from '#angular/core';
import { Observable } from 'rxjs';
import { DBService, Group} from '../db.service';
import { HttpClient } from '#angular/common/http';
import { NgIf } from '#angular/common/src/directives/ng_if';
import { element } from 'protractor';
import { ActivatedRoute } from '#angular/router';
import { Router } from '#angular/router';
#Component({
selector: 'app-flow',
templateUrl: './flow.component.html',
styleUrls: ['../css.css']
})
export class FlowComponent implements OnInit {
groups: Group[];
constructor(
private auth: AuthenticationService,
private dbService: DBService,
private route: ActivatedRoute,
private router: Router
) {}
ngOnInit() {
this.dbService.getGroup2().subscribe(groups => this.groups = groups);
}
}
DB Service Code
getGroup2(): Observable<Group[]> {
const url = 'http://localhost:4200/api/' + 'employees';
const data = ({
});
return this._http.post(url, data)
.pipe(
map((res) => {
console.log(res);
return <Group[]> res;
})
);
}
Backend
services/router.js
const express = require('express');
const router = new express.Router();
const employees = require('../controllers/employees.js');
router.route('/employees')
.get(employees.get);
module.exports = router;
services/database.js
const oracledb = require('oracledb');
const dbConfig = require('../config/database.js');
async function initialize() {
const pool = await oracledb.createPool(dbConfig.hrPool);
}
module.exports.initialize = initialize;
// close the function
async function close() {
await oracledb.getPool().close();
}
module.exports.close = close;
// simple executre function
function simpleExecute(statement, binds = [], opts = {}) {
return new Promise(async (resolve, reject) => {
let conn;
opts.outFormat = oracledb.OBJECT;
opts.autoCommit = true;
try {
conn = await oracledb.getConnection();
const result = await conn.execute(statement, binds, opts);
resolve(result);
} catch (err) {
reject(err);
} finally {
if (conn) { // conn assignment worked, need to close
try {
await conn.close();
} catch (err) {
console.log(err);
}
}
}
});
}
module.exports.simpleExecute = simpleExecute;
controllers/employees.js
const employees = require('../db_apis/employees.js');
async function get(req, res, next) {
try {
const context = {};
// context.id = parseInt(req.params.id, 10);
const rows = await employees.find(11);
if (req.params.id) {
if (rows.length === 1) {
res.status(200).json(rows[0]);
} else {
res.status(404).end();
}
} else {
res.status(200).json(rows);
}
} catch (err) {
next(err);
}
}
module.exports.get = get;
db_apis/employees.js
const database = require('../services/database.js');
const baseQuery =
`SELECT * FROM DB.EMPLOYEES`;
async function find(context) {
// let query = baseQuery;
// const binds = {};
// if (context.id) {
// binds.employee_id = context.id;
// query += `\nwhere employee_id = :employee_id`;
// }
const result = await database.simpleExecute(baseQuery);
console.log(result.rows);
return result.rows;
}
module.exports.find = find;
You have router.route('/employees').get(employees.get); but in your services you are doing this._http.post(url, data)
You should be doing a get request this._http.get(url)....
In your getGroup2, where is the headers part?
getGroup2(): Observable<Group[]> {
const url = 'http://localhost:4200/api/' + 'employees';
const data = ({
});
return this._http.post(url, data)
.pipe(
map((res) => {
console.log(res);
return <Group[]> res;
})
);
}
you must include the options
const headers = new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': `Bearer fs4df4sdfsd4fs`
});
const options = {headers: _headers}
return this._http.post(url, data, options)
Hope this helps 👍
I am writing an ember includedCommand for fetching and updating the app/index.html file - which uses NodeJS https and fs module to replace the indexFile by calling a function BuildIndexFile, where I am facing a weird issue -
When I perform command ember server --update-index - I can see the BuildIndexFile is being called and the https request is made to the remote server which downloads the file and gets written by fs.writeFileSync in app/index.html.
But when I perform ember update-index which is an included command, I can see BuildIndexFile has been called, and it reaches till console.log('Fetching index.html'); and I believe it is calling https.request... but it closes from there, I have no idea why the call didn't go through, when I debugged using node --inspect-brk ./node_modules/.bin/ember update-index I can see the https is available on the file, but not executing.
I am attaching my sample code available as a in-repo-addon available at lib/hello/index.js -
/* eslint-env node */
'use strict';
const parseArgs = require('minimist');
const watchman = require('fb-watchman');
let client = new watchman.Client();
client.capabilityCheck({optional: [], required: ['relative_root']}, function (error, response) {
if (error) {
console.log(error);
}
console.log('Watchman', response);
});
const ServeCommand = require('ember-cli/lib/commands/serve');
const ARGS = parseArgs(process.argv.slice(2));
const fs = require('fs');
const https = require('https');
module.exports = {
name: 'hello',
isDevelopingAddon() {
return true;
},
includedCommands: function() {
var self = this;
return {
hello: ServeCommand.extend({
name: 'hello',
description: 'A test command that says hello',
availableOptions: ServeCommand.prototype.availableOptions.concat([{
name: 'updateindex',
type: String
}]),
run: function(commandOptions, rawArgs) {
console.log(commandOptions, rawArgs);
if (commandOptions['updateindex']) {
console.log('Update Index')
}
const sampleHelloPromise = sampleHello();
const servePromise = this._super.run.apply(this, arguments);
return Promise.all([sampleHelloPromise, servePromise]);
}
}),
updateIndex: {
name: 'update-index',
description: 'Update Index File',
availableOptions: [{
name: 'index-file',
type: String
}],
run: function(commandOptions, rawArgs) {
BuildIndexFile(self.project.root, 'https://yahoo.com', {});
}
}
}
},
preBuild: function(result) {
let self = this;
if (ARGS['update-index']) {
BuildIndexFile(self.project.root, 'https://google.com', {}).then(function() {
delete ARGS['update-index'];
})
.catch(function(e) {
console.log(e);
});;
}
}
};
async function sampleHello() {
return await new Promise(resolve => {
setTimeout(() => resolve('hello'), 2000);
})
}
const BuildIndexFile = (rootPath, target, headers) => {
try {
debugger;
const indexFile = `${rootPath}/app/index.html`;
let noIndexFile = !fs.existsSync(indexFile);
return new Promise(function (resolve, reject) {
let options = {
hostname: target.replace(/^http(?:s):\/\//i, ''),
port: 443,
method: 'GET'
};
let dataContent = '';
console.log('Fetching index.html');
var request = https.request(options, function(response) {
response.on('data', function(d) {
dataContent += d;
});
response.on('end', function() {
fs.writeFileSync(indexFile, dataContent);
return resolve();
});
});
request.on('error', function(e) {
console.log(e);
return reject(`Error: Creating Index File`);
});
request.end();
});
} catch(e) {
throw e;
}
}
I'm writing unit-tests, where I need to set a mock response for a function within a function.
This is the function I want to mock:
cassandraDriver.js
module.exports = ({
cassandra_user,
cassandra_password,
cassandra_address
}) => {
if (!cassandra_address.length) throw Error('Cassandra address is not valid')
return new Promise((resolve, reject) => {
try {
const client = new driver.Client({
contactPoints: cassandra_address.split(','),
authProvider: authProvider(cassandra_user, cassandra_password),
queryconfig: {
consistency: driver.types.consistencies.quorum
}
})
return resolve(client)
} catch (e) {
reject(e)
}
})
}
This is the file that uses it:
const {
cassandraDriver
} = require('./lib')
module.exports = async ({
username = 'cassandra', //default values
password = 'cassandra', //default values
address,
keyspace,
replication_factor = 1,
migration_script_path,
logger = require('bunyan').createLogger({name: 'BuildCassandra'})
} = {}) => {
try {
const client = await cassandraDriver(username, password, address)
}).catch(err => {
throw Error(err)
})
} catch (e) {
logger.error(e)
throw e
}
}
How can I mock the call to 'cassandraDriver' in unit-tests? I tried using rewire, but the method is not exposed as it normally would be.
Thanks in advance.
let's modify your function so that it can accept a mock driver instead of cassandraDriver
const {
cassandraDriver
} = require('./lib')
module.exports = async ({
username = 'cassandra',
password = 'cassandra',
address,
keyspace,
replication_factor = 1,
migration_script_path,
logger = require('bunyan').createLogger({
name: 'BuildCassandra'
}),
driver = cassandraDriver
} = {}) => {
try {
const client = await driver(
username,
password,
address
})
} catch (e) {
logger.error(e)
throw e
}
}
(i also removed a superfluous .catch block)
next, you should create a "cassandra-driver-mock.js" which emulates the behaviour of the cassandra driver for your unit tests
the unit tests, of course, would pass the mock instead of the real driver as an option parameter
You can stub the module which exports cassandraDriver in your test file:
import cassandraDriver from "<path-to-cassandraDriver.js>";
jest.mock("<path-to-cassandraDriver.js>", () => jest.mock());
cassandraDriver.mockImplementation(() => {
// Stub implementation and return value
});
See Manual Mocks for more information.
I am writing test case for API where I have passed params and main file method is calling http request to get the data, So core() is basically calling the API and getting the response. This is just backend code that we have to test using jasemine.
First how to see response in test case if that's matched with success that is defined in test.
What is a correct way to write test in below scenario.
balance.spec.ts
import { GetAccountBalance } from './GetAccountBalance.node'
import { Promise } from 'es6-promise'
import { HttpRequest } from '../../../core/http/HttpRequest.node'
import * as sinon from 'sinon'
import { getValidationError } from '../../../common/ValidationErrorFactory'
// for easy mocking and cleanup
const sandbox = sinon.createSandbox()
afterAll(function afterTests () {
sandbox.restore()
})
describe('getAccountBalance', function () {
// the module under test
const module = new GetAccountBalance()
const testURL = 'https://essdd.max.com:4535'
const urlPath = '/webServices/instrument/accountBalance'
const fullURL = testURL + urlPath
const options = { isJSON: true }
let result
const stubbedEC = sandbox.spy(getValidationError)
const stubbedHttp = sandbox.createStubInstance(HttpRequest)
const success = {
header: {
serviceName: 'accountBalance',
statusCode: '0000',
statusDesc: 'SUCCESS',
},
response: {
balanceAccount: '6346.44',
},
}
const params = { Id: '21544', appName: 'instrucn', channelName: 'Web' }
describe('core() is called with correct params', function () {
beforeEach(function () {
result = module.core(params, stubbedHttp)
})
it('it should return the response from server', function () {
// Invoke the unit being tested as necessary
result.then((data) => {
expect(data).toBe(success)
})
})
})
})
getaccountBalnce.ts
public core(args: IAccountBalanceParam, httpRequest: HttpRequestBase): Promise<any> {
console.log('enter core');
const DBPLurl: string = this.constructDBPLurl(args);
const DBPLrequest: IAccountBalanceDBPLParam = this.constructDBPLrequest(args);
return Promise.resolve(httpRequest.makeRequest(DBPLurl, DBPLrequest, {isJSON: true}));
}