To my experience, our tests should not be bound by dependencies which execution are out of our control.
First of all, let's narrow down the scope of the tests. As stated in the question, the service under test is A, so let's focus on testing A regardless the ownership of B and its state (working, running, buggy, under heavy load, etc).
One important thing to achieve with tests is determinism. The only way we have to guarantee the correct behaviour of A (according to the premises of the (non-)functional requirements) is implementing tests that allow us to reproduce the cases to satisfy. Over and over, no matter the moment or the environment.
A way to achieve determinism is implementing test doubles. Mocks, stubs, dummies, spies ... So we can reproduce (by programming or configuration) the scenarios we need to cover.
Some might argue that this is not an integration test. To me, integrations might involve several components working together of all sort of natures. Some are under our control, others are not. Is good to be capable of isolating all the integrations, so we can check our component's behaviour under several and different integration conditions. It's especially good when we can isolate dependencies that slow down our testing because it also slows down our time-to-market.
The problem I see is service B updates a database so any integration
tests in service A will have to reset any changes they make by calling
the DB directly.
B writing in DB is almost anecdotic. The problem is testing a real service B because we are -indirectly- testing B code and the environment where B is running at!
The real danger is on the unknown conditions under which B is living at the moment of testing. These conditions, in the worst of the cases, could make our test not to pass. If they fail, they do it due to issues unrelated to the code. These fails don't give us meaningful feedback about the state of the code being tested.
As commented, writing in DB is anecdotic, there are many more things that could go wrong.
- Service B has no test environment.
- Service B has a test environment but has been deployed a new version which includes breaking changes.
- Service B is buggy.
- Service B data storage is down or temporarily unavailable.
- Service B responds with corrupt data.
- Service B is under test, and the data is frequently changing.
- Service B is no longer available.
You should be wondering why non-deterministic tests are dangerous? I suggest reading Fowler's blog about Erradicating non-determinism in tests and check out the following question too. Doc's answer summarises the subject very well.
Examples of non-deterministic tests are Flaky tests. Flaky tests are tests that fail due to undetermined circumstances. These tests fail now and then and we don't know why. We can not reproduce the issue.
A test suite with flaky tests can become a victim of what Diana Vaughan calls normalization of deviance - the idea that over time we can become so accustomed to things being wrong that we start to accept them as being normal and not a problem.
-Building Microservices- by Sam Newman
The normalization of deviance is the seed of the evil.
Any advice or thoughts?
When testing integrations, neither the data nor the behaviour of the external service should worry you. At least not yet. 1
What should worry you is to test the correct consumption of interface (API) and the proper handling of the feedback (error handling, deserialization, mappings, etc). In other words, the contract.
Lately, I have started to work with the concept of Test Doubles and Consumer Driven Contracts tests with very positive results.
It's true that they require additional efforts addressed to build and maintain these tests. That's our case. However, we have reduced the building, the testing and the deployment time significantly and we get faster and more meaningful feedback from CI.
In line with the above writing and @Justin's answer, you might be interested in tools like Mountebank.
1: There are a place for tests addressed to validate the real behaviour of external services. They can be placed out of the building pipeline. They might or might not be essential for a green deployment. That depends on whether you can or not circumvent the issues raised by the service. It's almost a political question rather than technical.