cancel
Showing results forย 
Search instead forย 
Did you mean:ย 

Test of service does not trigger custom handlers.

Mikkelj
Explorer
0 Kudos

Hi Guys,
I'm trying to write some high level integration test for my CAP service, but i ran into an issue that i hope you clever people can help with ๐Ÿ™‚ - it will be a two in one question..

in my custom handler, i have a method that increments the employee_number on the srv.before create event.

When i create an entity through http client or through any custom handler, it increments the employee_number, but when i do it from my test case (Entity.test.js), it doesn't go to the custom handler.

In my test case, i run service.create which usualy works to hit the service implementation. when i run following code, i does create an entity, but it skips the srv.before event. My test looks something like this:

// entity from schema
entity dummy : cuid{
     name: String;
     age: String,
     employee_number: Integer
}

describe('test CRUD', () => {

   test('Create entity', async () => {})
    const srv = cds.connect.to('ServiceName')

    const oResponse = srv.create(dummy).entries([{name: 'test', age: 'old!"}])
expect(oRespons).toHaveProperty('employee_id', expect.any(Number)) })

The following code fails, with no property called employee_id which should be added in the before event.

So my question here is - can't your full service (all custom handlers) by using srv?

Here comes my second question. To avoid the above scenario, i wanted to test using the cds.test POST, but i have authentication on the service so i get a 401 no authorized when using the POST method.

I tried with cds.spawn({user: cds.User.Priviliged}, () => {....}) but that blows up on me ๐Ÿ™‚

Any help will be appreciated! - Thanks in advance ๐Ÿ™‚

/Mikkel

Accepted Solutions (1)

Accepted Solutions (1)

Testing services that require authorization using cds.test:

1. Use mock authentication. I suppose your case does not involve any remote calls that require a really authenticated user. By default there are 2 users bob and alice with no passwords. You can additional or modify their roles to your needs.

$ cds env ls requires.auth
requires.auth.kind = mocked-auth
requires.auth.strategy = mock
requires.auth.users.* = true
requires.auth.users.alice.roles = [ 'admin' ]
requires.auth.users.bob.roles = [ 'builder' ]

2. Set axios.default.headers with AUthorization, so that it is send in every request.

const authtoken = 'Basic ' + Buffer.from('alice:').toString('base64') 
require("axios").defaults.headers.common.Authorization = authtoken 

const {GET} = cds.test();

const {data} = await GET '/catalog/Books'

Then your requests from tests will be authenticated. Authorization depends on the roles you assign to the user. You could also add the headers to every request by hand.

const authtoken = 'Basic ' + Buffer.from('alice:').toString('base64') 

const test = cds.test();
const {data} = await test.get('/catalog/Books',{headers:{Authorization: authtoken}} )
Mikkelj
Explorer
0 Kudos

Amazing Dinu! This is exactly what i needed to get the authentication to work - thanks a lot ๐Ÿ˜‰

Answers (3)

Answers (3)

gregorw
Active Contributor

Have you checked out the test samples at https://github.com/SAP-samples/cloud-cap-samples/tree/main/test?

Mikkelj
Explorer
0 Kudos

Hey guys, thanks for the replies.

I should've ofcourse said that the code i wrote is pseudo - in the actual code i have the awaits and all and it is working beside the described issue.

martin.stenzig3

have you tried that approach with a service that has authentication and authorization on? - i get a 401 Unauthorzied when trying to invoke the service like that. Do you know how to use a mock user or to use cds.User.Priviliged?

gregorw

I tried to use the different approach as shown in the samples. With SELECT and cql i get data direcetly from database, so i can't the service layer and custom handlers using that approach.
That leaves me with the optiton to connect to the service by using cds.connect.to('Service'), unfortunatly, this also skips the custom implementation.

martinstenzig
Contributor
0 Kudos

I think in simple terms, you are missing some "awaits". With the new cds.test package, I would go with something like this...


const cds = require('@sap/cds/lib')
const { POST, expect } = cds.test(__dirname + '/..').verbose(true)

describe('CAP Dummy Test', function () {

  before(async () => {

  })

  it('should create an entity', async () => { // Jest & Mocha style

    const { data, status } = await POST('/admin/dummy', {
      "name": "dummy1",
      "age": "dummy",
      "employee_number": 16
    })

    expect(status).to.eql(201)
  })
})