Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Matching a number causes expected type vs actual type mismatch #94

Closed
louis-quaintance opened this issue Sep 11, 2017 · 16 comments
Closed

Comments

@louis-quaintance
Copy link

Hi there,

Really love this library! however I'm getting an issue around matching on a number. When I use

somethingLike(50000) but my service sends or actually returns a float I get this error

{"gross_income":{"EXPECTED_TYPE":"Fixnum","ACTUAL_TYPE":"Float"}}]}

Is there a workaround for this?

Many thanks

Louis

@lirantal
Copy link
Contributor

I think there was a related issue about numbers and floats specifically for JavaScript.
Regardless, you either want to match a number or a float, if you want to match on a float then make sure you send 50000.0 and also match on it with somethingLike(50000.0)

@louis-quaintance
Copy link
Author

Thanks for your reply can u see any issues with what my expectation is

{
  state: 'i have a list of incomes to calculate tax for',
  uponReceiving: 'a request for a tax calculation',
  withRequest: {
    method: 'POST',
    path: '/v1/incomes-in-batch',
    headers: {
      Accept: 'application/json',
      'Content-Type': 'application/json',
    },
    body: {
      "items": eachLike(
        {
          "apply_tax_reduction_thresholds": like(true),
          "incomes": eachLike(
            {
              "gross_income": like(50000.0),
              "income_period": like("ANNUALLY"),
              "type": like("income")
            }
          )
        }
      )
    }
  },
  willRespondWith: {
    status: 200,
    body: {
      results: like([
        {
          gross_income: like(50000.0),
          net_income: like(41300.0),
          total_tax: like(8700.0),
          tax_bands: like([
            {
              name: like('personal'),
              remaining: like(0.0),
              tax_rate: like(0.0)
            },
            {
              name: like('basic'),
              remaining: like(0.0),
              tax_rate: like(0.2)
            },
            {
              name: like('higher'),
              remaining: like(100000.0),
              tax_rate: like(0.4)
            },
            {
              name: like('additional'),
              remaining: like(9007199254590991),
              tax_rate: like(0.45)
            }
          ])
        }
      ])
    },
  },
}

I get [{"gross_income":{"EXPECTED_TYPE":"Fixnum","ACTUAL_TYPE":"Float"}}]}

@lirantal
Copy link
Contributor

@louisandkatherine see #77

@bethesque
Copy link
Member

bethesque commented Sep 11, 2017

^^^ Use 50000.1 not 50000.0 as javascript rounds anything with .0 precision to an integer.

@louis-quaintance
Copy link
Author

Thanks for your quick reply on this!

Is there no way we could not pass the type i.e. Number (accepts either), Float (accepts only floats), FixNum (accepts only integer) ? As an enhancement? What would be wrong about this?

Our requirement is that we may indeed send in the same field to an api a figure which could be an integer or a float depending on a user's income.

@bethesque
Copy link
Member

bethesque commented Sep 13, 2017 via email

@bethesque
Copy link
Member

What would be wrong is that one example specifying "float or integer" could pass 100 of the time, and still only allow one of the two types, and you can't tell from that specification which one. You need to exercise both paths separately to be sure that both are accepted. You're not specifying a schema here, you're specifying a test case.

@louis-quaintance
Copy link
Author

Thanks for your reply again on this! I will try with this, although some of our services return dynamic data, changing on the day etc, therefore matchers for numbers + floats etc are very useful

@saikrishna321
Copy link

@bethesque @mefellows

Sorry to bump a year old post 🙈

In that case, make one interaction with a float, and one with an integer.

provider response returns multiple objects with float and interger

[{
value: 21.0
},{
value: 22.0
}]

Consumer pact looks like

const EXPECTED_BODY = {
  count: like(5),
  products: eachLike({
    value: 21.1,
  }),
  start: like(101)
};

In this case how can we creat different interactions for float and Int as the response from provider will have both float and Interger

Can you please help on this?

@bethesque
Copy link
Member

I'm confused about your issue. As you saying the value of "value" may be either a float or an integer?

@saikrishna321
Copy link

@bethesque

value of "value" may be either a float or an integer?

yes

@mefellows
Copy link
Member

You would explictly need to write two separate test cases. One that only replies with floats from the provider, and another for integers in those same fields.

const EXPECTED_BODY = {
  count: like(5),
  products: eachLike({
    value: 21,
  }),
  start: like(101)
};

test case for floats:

const EXPECTED_BODY = {
  count: like(5),
  products: eachLike({
    value: 21.1,
  }),
  start: like(101)
};

@saikrishna321
Copy link

One that only replies with floats from the provider

So when the consumer shares the contract with GET /validPrices this endpoint from provider would respond floats for few fields and Integer for few fields.

R u saying the provider should respond only float and Integer based on an endpoint. Sorry, I'm quite not getting.

@etos
Copy link

etos commented Feb 28, 2019

We're experiencing a similar issue with a field, but this issue is compounded by the field containing null values for some records (upstream legacy which we cannot enrich).. This in effect means we require a PACT test to pass whether we have float, integer (if .0) or null values on a single field.

Doing as suggested, would mean faking / corralling a lot of unrealistic test data across 3 separate tests. This feels very undesirable and unrealistic to a real world API test case where records would be mixed.

I believe aLikeAny option is required so that fields can match against any terms from a list

@mefellows
Copy link
Member

If we were to take that matcher on board, it would have to come with a lot of warnings because the very nature of a LikeAny means there are multiple variants that need to be tested. By putting that single matcher in there, you are essentially stating "I know what I'm doing here, trust me". It will keep the provider honest, but it means the consumer may not have tested a particular variant.

Currently, as is stated above and in our docs, we have a very strict policy with matching fields.

On the other hand, it is a common challenge and I wonder if there is another way we can help with it.

@bethesque
Copy link
Member

This is an explanation of why we don't currently have a "LikeAny" https://docs.pact.io/faq#why-is-there-no-support-for-specifying-optional-attributes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants