Repository: iluwatar/java-design-patterns
Issue: Separated Interface pattern
Labels: epic: pattern
type: feature

https://www.youtube.com/watch?v=d3k-hOA7k2Y

Issue comments:
May I take this up and implement this pattern?
Sure @swarajsaaj, go ahead!

Pull request review comments:
In a sense it's architectural, but I would put it under `Structural` since this the scope is so small.
Please add explanation for term `SPI` here, since it may not be familiar to everybody.
Naming, I would suggest `DomesticTaxCalculator`
Naming, `ForeignTaxCalculator` maybe?
```suggestion
  public void testTaxCalculation(){
```
```suggestion
  public void testTaxCalculation(){
```
I think we can add https://en.wikipedia.org/wiki/Service_provider_interface link as well?
Renamed

Fixed in another commit.


Fixed in another commit.

Added the definition and link to wikipedia for better understanding

Patch that resolved the issue:
diff --git a/pom.xml b/pom.xml
index da3084ab2c51..1026685881db 100644
--- a/pom.xml
+++ b/pom.xml
@@ -196,6 +196,7 @@
         <module>transaction-script</module>
         <module>filterer</module>
         <module>factory</module>
+        <module>separated-interface</module>
     </modules>
 
     <repositories>
diff --git a/separated-interface/README.md b/separated-interface/README.md
new file mode 100644
index 000000000000..ca7a12e44d95
--- /dev/null
+++ b/separated-interface/README.md
@@ -0,0 +1,119 @@
+---
+layout: pattern
+title: Separated Interface
+folder: separated-interface
+permalink: /patterns/separated-interface/
+categories: Structural
+tags:
+ - Decoupling
+---
+
+
+## Intent
+Separate the interface definition and implementation in different packages. This allows the client to be completely unaware of the implementation.
+
+## Explanation
+
+Real world example
+
+> An Invoice generator may be created with ability to use different Tax calculators that may be added in the invoice depending upon type of purchase, region etc.         
+
+In plain words
+
+> Separated interface pattern encourages to keep the implementations of an interface decoupled from the client and its definition, so the client is not dependent on the implementation.
+
+A client code may abstract some specific functionality to an interface, and define the definition of the interface as an SPI ([Service Programming Interface](https://en.wikipedia.org/wiki/Service_provider_interface) is an API intended and open to be implemented or extended by a third party). Another package may implement this interface definition with a concrete logic, which will be injected into the client code at runtime (with a third class, injecting the implementation in the client) or at compile time (using Plugin pattern with some configurable file).
+
+**Programmatic Example**
+
+**Client** An Invoice generator class accepts the cost of the product and calculates the total amount payable inclusive of tax
+
+```java
+public class InvoiceGenerator {
+
+  private final TaxCalculator taxCalculator;
+
+  private final double amount;
+
+  public InvoiceGenerator(double amount, TaxCalculator taxCalculator) {
+    this.amount = amount;
+    this.taxCalculator = taxCalculator;
+  }
+
+  public double getAmountWithTax() {
+    return amount + taxCalculator.calculate(amount);
+  }
+
+}
+```
+The tax calculation logic is delegated to the ```TaxCalculator``` interface
+
+```java
+
+public interface TaxCalculator {
+
+  double calculate(double amount);
+
+}
+
+```
+
+**Implementation package**
+In another package (which the client is completely unaware of) there exist multiple implementations of the ```TaxCalculator``` interface
+```ForeignTaxCalculator``` which levies 60% tax for international products.
+```java
+public class ForeignTaxCalculator implements TaxCalculator {
+
+  public static final double TAX_PERCENTAGE = 60;
+
+  @Override
+  public double calculate(double amount) {
+    return amount * TAX_PERCENTAGE / 100.0;
+  }
+
+}
+```
+
+```DomesticTaxCalculator``` which levies 20% tax for international products.
+```java
+public class DomesticTaxCalculator implements TaxCalculator {
+
+  public static final double TAX_PERCENTAGE = 20;
+
+  @Override
+  public double calculate(double amount) {
+    return amount * TAX_PERCENTAGE / 100.0;
+  }
+
+}
+```
+
+These both implementations are instantiated and injected in the client class by the ```App.java``` class
+
+```java
+    var internationalProductInvoice = new InvoiceGenerator(PRODUCT_COST, new ForeignTaxCalculator());
+
+    LOGGER.info("Foreign Tax applied: {}", "" + internationalProductInvoice.getAmountWithTax());
+
+    var domesticProductInvoice = new InvoiceGenerator(PRODUCT_COST, new DomesticTaxCalculator());
+
+    LOGGER.info("Domestic Tax applied: {}", "" + domesticProductInvoice.getAmountWithTax());
+```
+
+## Class diagram
+![alt text](./etc/class_diagram.png "Separated Interface")
+
+## Applicability
+Use the Separated interface pattern when
+
+* You are developing a framework package, and your framework needs to call some application code through interfaces.
+* You have separate packages implementing the functionalities which may be plugged in your client code at runtime or compile-time.
+* Your code resides in a layer that is not allowed to call the interface implementation layer by rule. For example, a domain layer needs to call a data mapper.
+
+## Tutorial 
+
+* [Separated Interface Tutorial](https://www.youtube.com/watch?v=d3k-hOA7k2Y)
+
+## Credits
+
+* [Martin Fowler](https://www.martinfowler.com/eaaCatalog/separatedInterface.html)
diff --git a/separated-interface/etc/separated-interface.urm.puml b/separated-interface/etc/separated-interface.urm.puml
new file mode 100644
index 000000000000..eab2ad60c98e
--- /dev/null
+++ b/separated-interface/etc/separated-interface.urm.puml
@@ -0,0 +1,36 @@
+@startuml
+package com.iluwatar.separatedinterface {
+  class App {
+    - LOGGER : Logger {static}
+    + PRODUCT_COST : double {static}
+    + App()
+    + main(args : String[]) {static}
+  }
+}
+package com.iluwatar.separatedinterface.taxes {
+  class DomesticTaxCalculator {
+    + TAX_PERCENTAGE : double {static}
+    + DomesticTaxCalculator()
+    + calculate(amount : double) : double
+  }
+  class ForeignTaxCalculator {
+    + TAX_PERCENTAGE : double {static}
+    + ForeignTaxCalculator()
+    + calculate(amount : double) : double
+  }
+}
+package com.iluwatar.separatedinterface.invoice {
+  class InvoiceGenerator {
+    - amount : double
+    - taxCalculator : TaxCalculator
+    + InvoiceGenerator(amount : double, taxCalculator : TaxCalculator)
+    + getAmountWithTax() : double
+  }
+  interface TaxCalculator {
+    + calculate(double) : double {abstract}
+  }
+}
+InvoiceGenerator -->  "-taxCalculator" TaxCalculator
+DomesticTaxCalculator ..|> TaxCalculator 
+ForeignTaxCalculator ..|> TaxCalculator 
+@enduml
\ No newline at end of file
diff --git a/separated-interface/pom.xml b/separated-interface/pom.xml
new file mode 100644
index 000000000000..da7584a93b6e
--- /dev/null
+++ b/separated-interface/pom.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<!--
+
+    The MIT License
+    Copyright © 2014-2019 Ilkka Seppälä
+
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to deal
+    in the Software without restriction, including without limitation the rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+    THE SOFTWARE.
+
+-->
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>com.iluwatar</groupId>
+    <artifactId>java-design-patterns</artifactId>
+    <version>1.24.0-SNAPSHOT</version>
+  </parent>
+  <artifactId>separated-interface</artifactId>
+  <dependencies>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-engine</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-params</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-core</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-assembly-plugin</artifactId>
+        <executions>
+          <execution>
+            <configuration>
+              <archive>
+                <manifest>
+                  <mainClass>com.iluwatar.separatedinterface.App</mainClass>
+                </manifest>
+              </archive>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/separated-interface/src/main/java/com/iluwatar/separatedinterface/App.java b/separated-interface/src/main/java/com/iluwatar/separatedinterface/App.java
new file mode 100644
index 000000000000..1951e738b77d
--- /dev/null
+++ b/separated-interface/src/main/java/com/iluwatar/separatedinterface/App.java
@@ -0,0 +1,62 @@
+/*
+ * The MIT License
+ * Copyright © 2014-2019 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.iluwatar.separatedinterface;
+
+import com.iluwatar.separatedinterface.invoice.InvoiceGenerator;
+import com.iluwatar.separatedinterface.taxes.DomesticTaxCalculator;
+import com.iluwatar.separatedinterface.taxes.ForeignTaxCalculator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * <p>The Separated Interface pattern encourages to separate the interface definition and
+ * implementation in different packages. This allows the client to be completely unaware of the
+ * implementation.</p>
+ *
+ * <p>In this class the {@link InvoiceGenerator} class is injected with different instances of
+ * {@link com.iluwatar.separatedinterface.invoice.TaxCalculator} implementations located in separate
+ * packages, to receive different responses for both of the implementations.</p>
+ */
+public class App {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
+
+  public static final double PRODUCT_COST = 50.0;
+
+  /**
+   * Program entry point.
+   *
+   * @param args command line args
+   */
+  public static void main(String[] args) {
+    //Create the invoice generator with product cost as 50 and foreign product tax
+    var internationalProductInvoice = new InvoiceGenerator(PRODUCT_COST,
+        new ForeignTaxCalculator());
+    LOGGER.info("Foreign Tax applied: {}", "" + internationalProductInvoice.getAmountWithTax());
+
+    //Create the invoice generator with product cost as 50 and domestic product tax
+    var domesticProductInvoice = new InvoiceGenerator(PRODUCT_COST, new DomesticTaxCalculator());
+    LOGGER.info("Domestic Tax applied: {}", "" + domesticProductInvoice.getAmountWithTax());
+  }
+}
diff --git a/separated-interface/src/main/java/com/iluwatar/separatedinterface/invoice/InvoiceGenerator.java b/separated-interface/src/main/java/com/iluwatar/separatedinterface/invoice/InvoiceGenerator.java
new file mode 100644
index 000000000000..c17ed5ac55e3
--- /dev/null
+++ b/separated-interface/src/main/java/com/iluwatar/separatedinterface/invoice/InvoiceGenerator.java
@@ -0,0 +1,51 @@
+/*
+ * The MIT License
+ * Copyright © 2014-2019 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.iluwatar.separatedinterface.invoice;
+
+/**
+ * InvoiceGenerator class generates an invoice, accepting the product cost and calculating the total
+ * price payable inclusive tax (calculated by {@link TaxCalculator}).
+ */
+public class InvoiceGenerator {
+
+  /**
+   * The TaxCalculator interface to calculate the payable tax.
+   */
+  private final TaxCalculator taxCalculator;
+
+  /**
+   * The base product amount without tax.
+   */
+  private final double amount;
+
+  public InvoiceGenerator(double amount, TaxCalculator taxCalculator) {
+    this.amount = amount;
+    this.taxCalculator = taxCalculator;
+  }
+
+  public double getAmountWithTax() {
+    return amount + taxCalculator.calculate(amount);
+  }
+
+}
\ No newline at end of file
diff --git a/separated-interface/src/main/java/com/iluwatar/separatedinterface/invoice/TaxCalculator.java b/separated-interface/src/main/java/com/iluwatar/separatedinterface/invoice/TaxCalculator.java
new file mode 100644
index 000000000000..aa4b81a84995
--- /dev/null
+++ b/separated-interface/src/main/java/com/iluwatar/separatedinterface/invoice/TaxCalculator.java
@@ -0,0 +1,30 @@
+/*
+ * The MIT License
+ * Copyright © 2014-2019 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.iluwatar.separatedinterface.invoice;
+
+public interface TaxCalculator {
+
+  double calculate(double amount);
+
+}
diff --git a/separated-interface/src/main/java/com/iluwatar/separatedinterface/taxes/DomesticTaxCalculator.java b/separated-interface/src/main/java/com/iluwatar/separatedinterface/taxes/DomesticTaxCalculator.java
new file mode 100644
index 000000000000..788afb90ab85
--- /dev/null
+++ b/separated-interface/src/main/java/com/iluwatar/separatedinterface/taxes/DomesticTaxCalculator.java
@@ -0,0 +1,40 @@
+/*
+ * The MIT License
+ * Copyright © 2014-2019 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.iluwatar.separatedinterface.taxes;
+
+import com.iluwatar.separatedinterface.invoice.TaxCalculator;
+
+/**
+ * TaxCalculator for Domestic goods with 20% tax.
+ */
+public class DomesticTaxCalculator implements TaxCalculator {
+
+  public static final double TAX_PERCENTAGE = 20;
+
+  @Override
+  public double calculate(double amount) {
+    return amount * TAX_PERCENTAGE / 100.0;
+  }
+
+}
diff --git a/separated-interface/src/main/java/com/iluwatar/separatedinterface/taxes/ForeignTaxCalculator.java b/separated-interface/src/main/java/com/iluwatar/separatedinterface/taxes/ForeignTaxCalculator.java
new file mode 100644
index 000000000000..c2b12e2f5637
--- /dev/null
+++ b/separated-interface/src/main/java/com/iluwatar/separatedinterface/taxes/ForeignTaxCalculator.java
@@ -0,0 +1,40 @@
+/*
+ * The MIT License
+ * Copyright © 2014-2019 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.iluwatar.separatedinterface.taxes;
+
+import com.iluwatar.separatedinterface.invoice.TaxCalculator;
+
+/**
+ * TaxCalculator for foreign goods with 60% tax.
+ */
+public class ForeignTaxCalculator implements TaxCalculator {
+
+  public static final double TAX_PERCENTAGE = 60;
+
+  @Override
+  public double calculate(double amount) {
+    return amount * TAX_PERCENTAGE / 100.0;
+  }
+
+}


Test patch:
diff --git a/separated-interface/src/test/java/com/iluwatar/separatedinterface/AppTest.java b/separated-interface/src/test/java/com/iluwatar/separatedinterface/AppTest.java
new file mode 100644
index 000000000000..4114f9bb73d0
--- /dev/null
+++ b/separated-interface/src/test/java/com/iluwatar/separatedinterface/AppTest.java
@@ -0,0 +1,41 @@
+/*
+ * The MIT License
+ * Copyright © 2014-2019 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.iluwatar.separatedinterface;
+
+import org.junit.jupiter.api.Test;
+
+import com.iluwatar.separatedinterface.App;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+
+/**
+ * Application test.
+ */
+class AppTest {
+
+  @Test
+  void shouldExecuteWithoutException() {
+    assertDoesNotThrow(() -> App.main(new String[]{}));
+  }
+}
diff --git a/separated-interface/src/test/java/com/iluwatar/separatedinterface/invoice/InvoiceGeneratorTest.java b/separated-interface/src/test/java/com/iluwatar/separatedinterface/invoice/InvoiceGeneratorTest.java
new file mode 100644
index 000000000000..ac75d3b70c69
--- /dev/null
+++ b/separated-interface/src/test/java/com/iluwatar/separatedinterface/invoice/InvoiceGeneratorTest.java
@@ -0,0 +1,48 @@
+/*
+ * The MIT License
+ * Copyright © 2014-2019 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.iluwatar.separatedinterface.invoice;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import static org.mockito.Mockito.*;
+
+public class InvoiceGeneratorTest {
+
+  private InvoiceGenerator target;
+
+  @Test
+  public void testGenerateTax() {
+    var productCost = 50.0;
+    var tax = 10.0;
+    TaxCalculator taxCalculatorMock = mock(TaxCalculator.class);
+    doReturn(tax).when(taxCalculatorMock).calculate(productCost);
+
+    target = new InvoiceGenerator(productCost, taxCalculatorMock);
+
+    Assertions.assertEquals(target.getAmountWithTax(), productCost + tax);
+    verify(taxCalculatorMock, times(1)).calculate(productCost);
+  }
+
+}
diff --git a/separated-interface/src/test/java/com/iluwatar/separatedinterface/taxes/DomesticTaxCalculatorTest.java b/separated-interface/src/test/java/com/iluwatar/separatedinterface/taxes/DomesticTaxCalculatorTest.java
new file mode 100644
index 000000000000..dac3ec2d6a28
--- /dev/null
+++ b/separated-interface/src/test/java/com/iluwatar/separatedinterface/taxes/DomesticTaxCalculatorTest.java
@@ -0,0 +1,41 @@
+/*
+ * The MIT License
+ * Copyright © 2014-2019 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.iluwatar.separatedinterface.taxes;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class DomesticTaxCalculatorTest {
+
+  private DomesticTaxCalculator target;
+
+  @Test
+  public void testTaxCalculation(){
+    target = new DomesticTaxCalculator();
+
+    var tax=target.calculate(100.0);
+    Assertions.assertEquals(tax,20.0);
+  }
+
+}
diff --git a/separated-interface/src/test/java/com/iluwatar/separatedinterface/taxes/ForeignTaxCalculatorTest.java b/separated-interface/src/test/java/com/iluwatar/separatedinterface/taxes/ForeignTaxCalculatorTest.java
new file mode 100644
index 000000000000..22526b6dfc13
--- /dev/null
+++ b/separated-interface/src/test/java/com/iluwatar/separatedinterface/taxes/ForeignTaxCalculatorTest.java
@@ -0,0 +1,41 @@
+/*
+ * The MIT License
+ * Copyright © 2014-2019 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.iluwatar.separatedinterface.taxes;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class ForeignTaxCalculatorTest {
+
+  private ForeignTaxCalculator target;
+
+  @Test
+  public void testTaxCalculation(){
+    target = new ForeignTaxCalculator();
+
+    var tax=target.calculate(100.0);
+    Assertions.assertEquals(tax,60.0);
+  }
+
+}