Unit testing against properties in an Apply with C...
# general
w
Unit testing against properties in an Apply with C#.... How do you do that? Assert's throw and exception, which is how the frameworks pick it up, but Exceptions in an Apply are swallowed. How do you get access to the value "outside" of the apply? or should I look at some kind of extension to extract the value outside the method and assert there?
@bored-oyster-3147 @tall-librarian-49374 any thoughts on this? As an example, I want to assert that there are 2 backendpools in a frontdoor instance...
Copy code
var frontdoor = resources.OfType<Frontdoor>().FirstOrDefault();
            var pools = frontdoor.BackendPools;
Therefore I'm not sure how to access the ImmutableArray on that to check the size
Right now, I'm having to do:
Copy code
var frontdoor = resources.OfType<Frontdoor>().FirstOrDefault();
            var backendPoolCount = 0;
            frontdoor.BackendPools.Apply(bp => {
                backendPoolCount = bp.Count();
                return false;
            });

            backendPoolCount.ShouldBe(1);
        }
which just feels dirty...
t
w
glad you sent that, that was what I was about to build... would be better if it was supplied, but I can see that it would be abused in a real scenario...
l
In .NET does that code work, @worried-knife-31967? In TS, it wouldn't: the code in the
Apply()
would happen asynchronously, and almost certainly after the
ShouldBe()
.
b
Well it is a race condition but he is mocking all of the other resources so I don't think he actually had any asynchronous dependents so he might've just got lucky that his code was executing synchronously causing that use of
.Apply
to work for him
l
There are libraries for async testing in Node. Hopefully there's similar support in .NET. The general pattern is to declare the test function async, and await the async code. Does that work in .NET?
b
yea that is what Mikhail suggested
l
Something like
Copy code
[TestMethod]
public async Task CorrectlyFailingTest()
{
  var frontdoor = resources.OfType<Frontdoor>().FirstOrDefault();
  (await frontdoor.BackendPools.Apply(bp => {
    return bp.Count();
  })).GetValueAsync().ShouldBe(1);
}
Ah yes, I see in that link,
GetValueAsync()
. Good stuff. Updated previous comment.
b
actually you don't use apply anymore you just await the output directly so:
Copy code
var backendPools = await frontdoor.BackendPools.GetValueAsync();
var backendPoolCount = backendPools.Count();
l
Nice. I want one of those for Node 🙂
t
Here you go
Copy code
const promise = <T>(output: pulumi.Output<T>): Promise<T | undefined> =>
  (output as any).promise() as Promise<T>;

it("should have a tag:key Name", async () => {
  const tags = await promise(vpc.tags);
  expect(tags).to.include.keys("Name");
  expect(tags?.Name).to.equal("my_app");
});
l
I use Chai As Promised.
Copy code
const promise = <T>(output: pulumi.Output<T>): Promise<T | undefined> =>
  (output as any).promise() as Promise<T>;

it("should have a tag:key Name", async () => {
  expect(vpc.tags).to.eventually.include.keys("Name");
  expect(vpc.tags?.Name).to.eventually.equal("my_app");
});
But it's not as nice as the .NET version. Something like
Copy code
const promise = <T>(output: pulumi.Output<T>): Promise<T | undefined> =>
it("should have a tag:key Name", async () => {
  expect(vpc.tags.getAsyncValue()).to.include.keys("Name");
  expect(vpc.tags?.Name.getAsyncValue()).to.equal("my_app");
});
Or even
expectAsync(vpc.tags).to.include.keys("Name")
.. tidier still.