Anyone here used Pact with aws-sdk-mock ? Am getti...
# pact-js
k
Anyone here used Pact with aws-sdk-mock ? Am getting problems with hitting pact trying to verify the endpoint
Copy code
Actual interactions do not match expected interactions for mock MockService.
t
The context around this error message will tell you why it thinks that
However, if you're using
aws-sdk-mock
, then you're probably not sending real requests. So, pact will be unhappy, because it wants the real request
😢 1
However, if you're using pact against the AWS sdk, you'll be in for a bad time, because the HTTP calls that that AWS SDK makes aren't part of the API contract
what are you trying to do?
k
in a nutshell, trying to implement pact with lambda functions.
t
Do you mean trying to test a lambda function with pact, or you're trying to test the http calls that your lambda makes with pact?
(or are you using message pacts?)
k
Yes, test a lambda function with pact
t
ok. So, you have a pact file from your consumer, and your lambda is the provider?
k
Correct
t
How is your lambda connected? Via an API gateway?
What you would usually do is spin up your provider (in this case, you probably deploy it to your test env, or wherever) and then run the pact verifier against it
In this way, there would be no
aws-sdk-mock
, because you're spinning up your real provider
however, if the lambda requires anything upstream, like a DB or other AWS services, you may want to mock those using the pact state change
usually I would do this as the first step in your lambda - where you would normally configure all those connectors, you just configure mock ones instead
alternatively, you can not deploy it, and test it locally. Then you could use aws-sdk-mock, I guess
it all depends on how your lambda is getting the http event
k
Apologies im fairly new to aws but yes the actual function that is called is connected via an api gateway with the aws-sdk. However in our test files we are using the aws-sdk-mock so that it doesnt need to call the actual endpoint.
t
There's also
localstack
, but my experience with that has not been positive
er
Pact needs to call the actual endpoint
that's what's under test
aws-sdk-mock
is for mocking out aws sdk calls - I assumed that your lambda is calling some AWS services, but do you mean that you're using it to mock the whole lambda invocation?
I think I'm confused about what you're trying to do
k
ahh i think i see where this is wrong. Sorry the test file is written by someone else. and it seems that they've used aws-sdk-mock to mock the whole lambda thingy. then calling our actual lambda function to see if the response matches the mocked lambda invocation
here's the code snippet.
Copy code
test('Should invoke the ConsumeLambda.', () => {
    AWSMock.setSDKInstance(AWS);
    AWSMock.mock('Lambda', 'invoke', function mockedInvoke(params, callback) {
      callback(null, {
        Payload: {
          statusCode: 200,
          body: {
            message: 'This token is valid',
            metadata: {}
          }
        }
      });
    });

    return invokeConsumeLambda('token', 'VALIDATE').then(data => {
      expect(data).toMatchObject({
        statusCode: 200,
        body: {
          message: 'This token is valid',
          metadata: {}
        }
      });
    });
  });
t
I don't know what is going on there, tbh
it sounds like maybe there's no API gateway, and you're invoking the lambda directly?
invokeConsumeLambda
<-- I think this is using the mock set up, rather than invoking it directly
k
so invokeConsumeLambda (bad name i know) is the actual function that calls aws with its aws endpoints and stuff
t
So this is the consumer side, not the provider size
k
yes this is on consumer side. the provider is
invokeConsumeLambda
t
yes, except it doesn't, because the code at the top just mocked out aws endpoints
k
Correct
t
So, this code illustrates the kind of problem that pact solves
what's happening here is that you're marking your own exam
"hey, I'm gonna mock this, so it returns X" "now I'll call it and check it returns X"
k
yeap i see it now
redundant test
👍 1
t
Pact has two more steps: "hey, I'm gonna mock this, so it returns X" "now I'll call it and check it returns X" "Ok, I'll write that down in the pact file that when I call with Y, it returns X" Then later "I'm going to check that the provider really does return X when called with Y"
The test shouldn't be entirely redundant, because usually
invokeConsumeLambda
would do things like: • Know how to make the call • Know how to marshal the request (eg
getUser(29)
becomes
GET /some/path/user/29
) • Know how to unmarshall the response
however, since the code is expecting the exact response from the AWS sdk, I think there's no unmarshalling going on
Other nice things about pact: • You only test the things you need - so in this case, the
metadata: {}
is returned. I bet you don't need it, so you don't need to tell pact about it
• You're testing that your client really can send the request
That last point is nice, because it means that you catch things like incorrectly invoked http library.
k
I see thank you so much for your advice. Right now the problem is that on the .addInteraction() my withRequest parameter is empty because i dont know what the endpoint is. So am i correct to assume that i need to set up the api gateway trigger on the lambda function and point it there ?
t
That's what I would do
note that your consumer test doesn't actually hit the real provider
k
yes that i know now
t
the consumer test will talk to pact
then when you go to test the provider, your real provider will be invoked by pact
real consumer -> pact pact -> real provider
because i dont know what the endpoint is.
Yeah. This is the problem with using pact to test the AWS sdk. The requests are opaque
k
😞
t
Well, it's kind of like a library. You don't test the DB connection part of a postgres lib
Similarly, you don't need to test the AWS connection part of the AWS SDK
However, in this case, I think: • You could continue with aws-sdk-mock, but you want some way to know that the mocked response is what the real lambda produces • The returned value from
aws-sdk-mock
suggests that the design of the layers could be improved • If you can change the design to bring in an API gateway, then you can just make an HTTP request as normal. Then you can use pact, and also your consumer implementation doesn't even need to know it's contacting AWS
👀 1
The returned value from aws-sdk-mock suggests that the design of the layers could be improved
Because the calling layer knows that it's a lamdba API response object. It shouldn't know that - probably it should just get
Copy code
{
          message: 'This token is valid',
          metadata: {}
        }
(although I don't know your application, so it's hard to say for sure) - this is unrelated to pact / aws-sdk-mock - it's just something I noticed
👀 1