Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best Practice: Testing Interface Contract Compliance?

Assume that interface for is defined

interface Foo {
  int getBaz();
  void doBar();
}

Further assume that the contract states that everytime doBar is called baz is incremented. (Ok this is a contrived bit of code but stick with me here)

Now I want to provide a unit test that I can provide to Foo implementers so that they can verify that they meet all the contract conditions.

class FooTest {
  protected Foo fooImpl;

  @Test
  public void int testBazIncrement()
  {
    int b = fooImpl getBaz();
    fooImpl.doBar();
    Assert.assertEquals( b+1, fooImpl.getBaz();
  }
}

What are the best practices for making the test available to the implemnters of Foo? It seems to me that there needs to be a mechanism for them to call the FooTest and provide a Foo or a FooFactory to construct Foo instances. Furthermore, if there are many tests (think big interface) then I want to put all those tests in one FooTest class.

Are there any best practices for how to implement such tests?

like image 268
cWarren Avatar asked Jan 08 '13 08:01

cWarren


People also ask

Is contract testing an integration test?

We often use contract testing to test an integration point between multiple services. They are used in APIs, microservices and so on.

How do you test an API contract?

Complete API contract testing must validate both the API producer (server side) and the API consumer (client side) to detect and diagnose when a contract is broken by either side. Contract testing is designed to monitor the API conversation that takes place between the API consumer and the API producer.

What is contract driven testing?

Consumer-driven Contract Testing (or CDC for short) is a software testing methodology used to test components of a system in isolation while ensuring that provider components are compatible with the expectations that consumer components have of them.

Is contract testing functional testing?

Contract testing is a lightweight form of API testing that strictly checks the content and format of requests and responses. Unlike functional tests, contract tests do not validate the logic or consumer flows of APIs.


1 Answers

This is a textbook example of Dependency Injection. If you use Spring as the DI container, you can wire in the fooImpl

@Inject
protected Foo fooImpl;

Your test needs to be annotated with @RunWith(SpringJUnit4ClassRunner.class), and it's up to the interface provider to configure Spring with their implementation.

Without a DI container, you can just create an abstract test class with all the tests in it and an abstract method to provide the implementation object.

protected abstract Foo createFoo();

It's up to the implementation provider to subclass the test and implement the abstract method.

class FooImplTest extends FooTestSuper {

@Override
protected Foo createFoo() {
    return new FooImpl();
}

If you have multiple tests, consider JUnit's @Suite annotation. It's compatible with the Spring test runner.

like image 120
artbristol Avatar answered Sep 28 '22 12:09

artbristol