pact-foundation / pact-net

.NET version of Pact. Enables consumer driven contract testing, providing a mock service and DSL for the consumer project, and interaction playback and verification for the service provider project.
https://pact.io
MIT License
846 stars 232 forks source link

Introduce mock as a part of provider tests #153

Closed sushant2517 closed 6 years ago

sushant2517 commented 6 years ago

This is more a question (feature request) than an issue -- Currently, when the provider test is executed against a pact contract, afaik, we need to spin up a mock test server as well as provide a mock database.

Instead of having to spin up a real test database, would it be useful if we are able to Mock the underlying repository implementation to provide mock responses. So, that way we can easily skip the whole db setup process and still verify most of the vertical slice.

I would be interested to give it a shot if this feature doesn't already exist.

Thanks, Sushant

neilcampbell commented 6 years ago

Hi @sushant2517 From a Pact perspective all you need to spin up is the test server, it's really up to you how you mock any data you depend on.

If you are using DI and IoC, you can totally override the IoC container with a mock repository implementation that returns pre-canned responses. That is generally how I mock out any data that the app uses. You would do this using the standard provider state hooks.

sushant2517 commented 6 years ago

Thanks Neil! Could you please point me to an example of how we could use repository mocking with provider states?

Thanks, Sushant

sushant2517 commented 6 years ago

Nevermind, found a way :)

neilcampbell commented 6 years ago

Nice one!

rikkiprince commented 5 years ago

@sushant2517 Could you share the way you found to do this? We're facing this exact problem and cannot figure out a decent way of updating the mock from a provider state.

Given the test server is already spun up, with its dependencies already set, how can I get the provider state action to change the mock.

rikkiprince commented 5 years ago

@neilcampbell Do you have any advice about how Provider States help here, and how you use them to adjust what your mock returns?

Or do you use the Provider State action to change the mock being used?

Or does your mock have some sort of hook accessible in the Provider State action (if so, is your mock a singleton, so it can be accessed in the Provider State?)

I guess I'm trying to figure out what your communication pipe is between the Provider State action and your mock, as we're struggling to make that connection in a satisfying way.

sushant2517 commented 5 years ago

@sushant2517 Could you share the way you found to do this? We're facing this exact problem and cannot figure out a decent way of updating the mock from a provider state.

Given the test server is already spun up, with its dependencies already set, how can I get the provider state action to change the mock.

Hi @rikkiprince, Apologies for the delayed response! We used DI to provide a mock implementation of the repository interface to the application bootstrap (for pact run based on the configuration). This allows the PACT mock server to instead use the mock implementation rather than the actual one. We can implement the mock implementation using pretty much any approach. We used MounteBank to provide mock services and wrapped these around the repository methods. Hope that helps!

neilcampbell commented 5 years ago

@rikkiprince I usually use the approach that @sushant2517 has mentioned.

rikkiprince commented 5 years ago

@sushant2517 @neilcampbell Thank you very much for your quick replies!

I don't think I quite follow how mountebank comes into this. I thought mountebank was for mocking/stubbing whole services? Do you mean in your service under test, you run the full service logic but use mountebank to mock the downstream services? Or do you mock the full service logic, and have that mock make calls to mounteback?

Also, this means to run these tests, you need the mountebank service up and running. This seems like it would impact performance and stability somewhat? We were hoping our CDC tests would be a fast and stable tests, closer to component and unit tests than acceptance tests.

Sorry if this all sounds like obvious stuff, but we're just beginning to build our understanding of CDC testing and Pact, and I think we might have some assumptions about those tests which don't hold true in practice, but I'd like to understand it better before sharing that!

sushant2517 commented 5 years ago

Hi @rikkiprince, Mountebank is not directly related to this stuff. I just suggested an approach to mock the repository layer in a central manner. It is beneficial to have the state managed centrally so that you can have the consumer and provider tests run in an automated pipeline. The key power of a CDC test is if both the provider and consumers are run in a chnage control process to make sure the contracts still hold for any change being pushed. But that being said, you can use any approach to mock your repository or service layer. Simplest would be to return hardcoded data within the code.

Hope that clarifies it!

rikkiprince commented 5 years ago

Hi @sushant2517, thank you again for continuing to clarify this!

We're definitely going to be integrating this into our test pipelines, but we're keen for CDC to run earlier in the pipe, which means we need it to be quick and stable (i.e. not reliant on a running service that might be down or suffering from networking issues).

I appreciate that this setup is flexible enough to use multiple approaches to mock the repository or service layer, it just seems a bit complex to have mocks which are setup per test. It seems to require a backchannel between the ProviderState action and the mock (mountebank seems to be an example of this backchannel, but I'm guessing we could use the file system, a database or IPC pipes), where as I was sort of expecting to have an in-memory mechanism for communicating that change of mock state between the test runner and the mock.