DiUS / pact-consumer-swift

A Swift / ObjeciveC DSL for creating pacts.
MIT License
98 stars 43 forks source link

Separate Pact providers generated files contain all the pacts #98

Open treatwell-ignasurbonas opened 4 years ago

treatwell-ignasurbonas commented 4 years ago

General Setting different providers in same tests run (provider when creating MockServer instance) doesn't generate correct output (pact json files). All the pacts are generated for every provider file. This is an issue because we need to generate (and later upload) separate pacts files for different providers.

Example Issue There are two providers: provider1 and provider2. MockService instance is created for each pact test. Provider for each test is set in initialiser:

public init(
    provider: String,
    consumer: String,
    pactVerificationService: PactVerificationService,
    errorReporter: ErrorReporter
  )

in test it looks:

class Pact1Tests: XCTestCase {
  func testPact1() {
    let mockServer = MockService(
        provider: "provider1",
        consumer: "consumer",
        pactVerificationService: PactVerificationService(url: <url>, port: 1234),
        errorReporter: Errors()
    )
    ...
  }
}

Remark: if you do it in override func setUp() - issue is still there.

After all tests finished, two pact files are generated: consumer-provider1.json and consumer-provider2.json. If generated file is opened, you can see that all the tests, even if created MockServer instance for specific test had different provider name, are in that json.

Workaround If you run tests separately for just provider1 and when just for provider2 (e.g. using test plans) files are generated correctly.

Summary Probably the issue is with provider parameter propagation and file generation.

I hope this information is enough. I can try to provide more info if needed.

P.S. when we run pact ruby mock server we do not specify consumer and provider as we do it in code when we are creating MockServer instance. pact-mock-service start --pact-specification-version $PACT_SPEC_VERSION --log $LOG --pact-dir $PACTS -p $PORT

andrewspinks commented 4 years ago

Hi @treatwell-ignasurbonas this is because of a limitation of how the underlying mock server works. i.e. one instance of the mock service should be for one provider. Most other pact implementations start and stop the mock service as part of the test framework, however this is not possible when running in a sandboxed environment like the iOS simulator.

The usual workaround that people use is to start multiple mock servers up at the beginning of the test phase running on different ports.

pact-mock-service start --pact-specification-version 2.0.0 --log "${SRCROOT}/tmp/provider1-pact.log" --pact-dir "${SRCROOT}/tmp/pacts" -p 1234
pact-mock-service start --pact-specification-version 2.0.0 --log "${SRCROOT}/tmp/provider2-pact.log" --pact-dir "${SRCROOT}/tmp/pacts" -p 2345

And then specify the port when setting up your test.

// Tests for Provider 1
let pactVerificationService = PactVerificationService(
  url: "https://localhost",
  port: 1234 // the port of the second mock service
)

animalMockService = MockService(
  provider: "Provider 1",
  consumer: "My iOS App",
  pactVerificationService: pactVerificationService
)

...
// Tests for Provider 2
let pactVerificationService = PactVerificationService(
  url: "https://localhost",
  port: 2345 // the port of the second mock service
)

animalMockService = MockService(
  provider: "Provider 2",
  consumer: "My iOS App",
  pactVerificationService: pactVerificationService
)

Also, there is a new implementation of the pactswift project which we are trialling which uses an in process mock service which doesn't have this limitation. https://github.com/surpher/PactSwift

surpher commented 4 years ago

If you still need to use multiple providers with Pact spec v2 (pact-consumer-swift), see this example project on how you could set it up (it's not the only way):

https://github.com/surpher/pact-consumer-swift-multiple-providers

treatwell-ignasurbonas commented 4 years ago

Amazing. Thank you for detailed explanation. This one instance of the mock service should be for one provider answers all my questions 👍 .