collectionVariables returns value by reference or by value

Hi community people,

I am trying to simulate a collection which has 2 request

  1. Get ProductId’s
  2. Post Request: Place Orders using productId’s returned from 1st response

image

I stored all productId’s from response1 in an array in a local variable and later set variables in 2 scopes as below

Case1: pm.variables.set
Case2: pm.collectionVariables.set

in each case, I am trying to get one productId from the given array and Place Order

Array automatically updated if I make use of pm.variable.get but if I make use of pm.collectionVariables.get , I specifically need to set collectionVariable (toolIds) after popping element from an array.

As I Understood in the case of Arrays or objects we get Object reference and operations over it automatically update original object as we get reference of object as in case1 here.

Please help me understand this.
Let me know if any update i have to make so that you follow my doubt.

Hey @vivek5080-05 :wave:

Welcome to the Postman Community! :postman:

In your first request, it’s using pm.variables.set() which only lives for the duration of that single request. It’s not storing those values in a variable anywhere.

The pm.variables.get() in your second request would go pick the variable with that name, which is in the narrowest scope and use that - It wouldn’t be using anything from the first request.

I would personally just stick to using collectionVariables for it all, that way you’re not getting tripped up by the way that pm.variables.get() works in Postman.

This is from a slightly different context but uses the .shift() method in the script that @michaelderekjones shared, It might be worth taking a look at.

@danny-dainton Thanks for the insights.
let me make myself more clear here so that i get more insights from experts

here I am not able to understand that, if i make use of collection Variables in my 1st request code i.e

pm.collectionVariables.set('toolIds',toolIds); instead of pm.variables.set('toolIds',toolIds);, 

why would i need to reset back my collection variable(toolIds) back in my request 2 .

Request1 code will be for case2

const jsonData=pm.response.json();
const toolIds=jsonData.map(tool => tool.id);
pm.collectionVariables.set('toolIds',toolIds);

Request 2 code will look like for case2

const toolIds = pm.CollectionVariables.get('toolIds');
pm.collectionVariables.set('currentToolId', toolIds.shift());

if (Array.isArray(toolIds) && toolIds.length > 0) {
    postman.setNextRequest('Submit order');
*pm.collectionVariables.set('toolIds', toolIds);*
} else {
    postman.setNextRequest(null);
}

Here line in Italics will be extra line of code if comapred with case1(pm.variables case) otherwise it will always take same element from array for placing an order.

Sample Order request Body will look like

Your logic is fine.

The examples I’ve posted previously uses the pre-request script to define the variable for the current request and to reduce the array, and the tests tab to control the loop.

I’m assuming that all of your request 2 code is in the pre-request script which will also work. The code I’ve used controls the loop in the tests tab, but it could go in the pre-request script as its only controlling the next request.

Thanks Mike,

Can you help me out in building my concepts better here,
why in case 2(when using pm.collectionVariables.get) we have to write this statement pm.collectionVariables.set(‘toolIds’, toolIds); extra as compared to case1(when using just pm.variables.get)

Scope.

As Danny has already mentioned, its better to use collection variables to avoid scope issues.

Once you’ve reduced your array using shift(). You need to re-save the array.

I’m surprised your case 1 actually works, as the variable you set using pm.variables.set() will not be available to request 2.

Let me show you an example of scope issues.

Request 1. (Just so I have an array to work with).

let toolIds = ["123", "456", "789"]

pm.collectionVariables.set("toolIds", toolIds);

console.log(pm.collectionVariables.get("toolIds")); // ["123", "456", "789"]

Request 2. All code in pre-request script.

let toolIds = pm.collectionVariables.get("toolIds");

console.log(toolIds); // ["123", "456", "789"]

pm.collectionVariables.set('currentToolId', toolIds.shift());

console.log(toolIds); // ["456", "789"]

console.log(pm.collectionVariables.get("toolIds")); // ["123", "456", "789"]

console.log(pm.collectionVariables.get("currentToolId"));  // "123"

The following is what is actually returned in the console logs.

image

The console log for the collection variable toolIds is only showing two elements when it should be showing all three still.

This is due to having toolIds set at the collection and local level.

If you move the last two console logs to the tests tab, then it works correctly as the local variable for toolIds no longer exists after the pre-request script has completed. It’s not available to the tests tab.

image

It is better to use different variable names for the collection variables and the local variables that you use temporarily.

It is more code, but it removes any potential scope issues.

let array = pm.collectionVariables.get("toolIds");

console.log(array); // ["123", "456", "789"]

let currentToolId = array.shift();

console.log(currentToolId);  // "123"
console.log(array); // ["456", "789"]

pm.collectionVariables.set("toolId", currentToolId);
pm.collectionVariables.set("toolIds", array);

console.log(pm.collectionVariables.get("toolIds")); // ["456", "789"]
console.log(pm.collectionVariables.get("toolId"));  // "123"

yes, my case 1 is working also, and in that too, i don’t have to set value explicitly as you did for case 2 like below at the end.

This is what I am not able to follow

Even in your code if we comment below 2 lines

and check toolIds variable value in collection scope it shows [“456”, “789”] which means the collection variable is already updated then why do we explicitly have to save this again pm.collectionVariables.set(“toolIds”, array);

in order to have the required functionality as expected.

Otherwise with fresh next request again it starts from initial element of array.

Open up the collections as a tab, so you can see it side by side with your request.

What you are seeing is the scope issue we are talking about, when it looks like the collection array has been updated when its actually just reading the value from the variable in the local scope instead.

When the request runs again, it will be back to 3 elements.

I’ll show this in action once more for you.

Pre-request script.

let toolIds = pm.collectionVariables.get("toolIds");

console.log("Pre-request script - toolIds - local variable");
console.log(toolIds); // ["123", "456", "789"]

pm.collectionVariables.set('currentToolId', toolIds.shift());

console.log("pre-request script - toolIDs - local variable after array.shift");
console.log(toolIds); // ["456", "789"]

console.log("Pre-request script - toolIDs collection variable");
console.log(pm.collectionVariables.get("toolIds")); // ["123", "456", "789"]
console.log("the above is incorrectly showing the local variable instead of the collection variable");

Tests tab. (Where I retrieve the collection variable again, but don’t have any local variables causing scope issues).

console.log("Tests tab - toolIDs collection variable");
console.log(pm.collectionVariables.get("toolIds")); // ["123", "456", "789"]
console.log("back to three elements as we didn't resave the toolId collection variable");

The resulting console logs.

image

The collection variables after the script has run. (Showing that the current value still has three elements in it).

image

Let me show you an example of this in action.

I have two requests.

Request 1.

Pre-request script. Setting an local variable and a collection variable.

pm.variables.set("testVariable1", "testValue1");
pm.collectionVariables.set("testVariable2", "testValue2");

Request 2. Test Tab.

console.log(pm.variables.get("testVariable1"));
console.log(pm.variables.get("testVariable2"));

Which works fine.

image

Local variables are scoped to the request, so they will be available in the pre-request script and tests tab.

Pre-request tab for Request 2.

console.log(pm.variables.get("testVariable1"));
console.log(pm.variables.get("testVariable2"));

It can still find the collection variable, but is returning undefined for the local variable.

image

When you use the collection runner, the variables will persist for that collection run. So technically, you can do what you are attempting, but you do run the danger of scope issues. My advice is to use collection variables to avoid any unpleasant surprises and to call any local variables different names.

@michaelderekjones Would creating a Collection in a Public Workspace help show this better?

Might be easier for @vivek5080-05 to see the workflow infront of them rather than in a series of pictures and log statements :pray:

@danny-dainton

Potentially, I did consider creating one for sharing answers but haven’t got around to doing it just yet.

I do have a collection of useful requests that I can probably add to it as a starter for 10.

We can work together on adding ones that you feel are either repeated solutions for topics or just generally really helpful things to reference, in the Postman Answers Public Workspace.

Seems like a great place for those to be. :trophy:

@michaelderekjones I got what you are trying to explain here
I understand that When one uses the collection runner, the variables will persist for that collection run and having the same name for variables(under different scopes) runs into issues.

but I think my question is a bit different or might be i am not able to make myself clear here.

let’s say we use only collectionVariables only and with different local variables name (i.e array for local variable and toolIds for collection variable), the illustration that you use intially as below

here i commented line 8 and verifies that collectionvariable toolIds is already updated and for next time same updated toolIds array value should be used [‘456’,‘789’] but then when next time same request ran again collectionvaraible toolIds set to [“123”,‘456’,‘789’] again.

does this mean that collectionVariables not persists for a particular collection run unless we set it explicitly again ?

In my example, you set a local variable from the collection variable.

You then use array shift to reduce the size of the array.

You then need to re-save the collection variable otherwise the next time you run the request and call the collection variable it will be the initial size.

When using local variables with the same name as the collection variable, then the variable will persist during the collection run but it can get messy with scope. When you try and read the collection variable, it will actually read the value of the local variable with the same name instead.

Using local variables with a different name to the collection variable removes any chance of scope issues. But it does mean to need to re-save the collection variable after you reduce the size of the array.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.