-1

I want to know what does this code mean:

mathApplication.setCalculatorService(calcService);

Why should I use an interface and make object from it? And what does this injection means?

Here is my Tester Code:

import org.easymock.EasyMock;
import org.easymock.EasyMockRunner;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(EasyMockRunner.class)
public class MathApplicationTester {

    private MathApplication mathApplication;
    private CalculatorService calcService;

    @Before
    public void setUp() {
        mathApplication = new MathApplication();
        calcService = EasyMock.createMock(CalculatorService.class);
        mathApplication.setCalculatorService(calcService);
    }

    @Test
    public void testAddAndSubtract() {

        //add the behavior to add numbers
        EasyMock.expect(calcService.add(20.0, 10.0)).andReturn(30.0);

        //subtract the behavior to subtract numbers
        EasyMock.expect(calcService.subtract(20.0, 10.0)).andReturn(10.0);

        //activate the mock
        EasyMock.replay(calcService);

        //test the subtract functionality
        Assert.assertEquals(mathApplication.subtract(20.0, 10.0), 10.0, 0);

        //test the add functionality
        Assert.assertEquals(mathApplication.add(20.0, 10.0), 30.0, 0);

        //verify call to calcService is made or not
        EasyMock.verify(calcService);
    }
}
Paolo Forgia
  • 6,572
  • 8
  • 46
  • 58
Wooopsa
  • 320
  • 1
  • 6
  • 22

1 Answers1

0

The MathApplication is dependent on a CalculatorService which provides - as its name suggests - service for calculations.

However, in unit tests, you want to test only the class under test (MathApplication), so you want to replace all the dependencies by your own implementation over which you have full control. For this purpose you use the mock.

calcService = EasyMock.createMock(CalculatorService.class);

Dependency injection is a pattern which "injects" the object you are dependent on into the main object.

There are three approaches to getting instances of objects you class depends on.

public class MathApplication {
    // I need an instance of CalculatorService inside the code of MathApplication
    ...
}

1: Instantiate the object inside the code of MathApplication (it doesn't matter if the calculatorService is local or a class attribute). This is not very recommendable way.

public double subtract(double a, double b) {
    CalculatorService calculatorService = new SomeFastCalculatorService();
    return calculatorService.subtract(a, b);
}

2: Delegate the task of instantiation to an external provider, called factory:

public double subtract(double a, double b) {
    CalculatorService calculatorService = CalculatorServiceFactory.getInstance();
    return calculatorService.subtract(a, b);
}

3: Let someone from outside inject the instance by providing an injection point, either via constructor of via a setter method.

It is used in general for building the "dependency tree" of you whole application (usually using frameworks such as Spring Dependency Injection or JavaEE CDI). Here it used to inject your mock object into the class under test:

mathApplication.setCalculatorService(calcService);

Later on, in your @Test method, you exactly set the behaviour of your mock object.

EasyMock.expect(calcService.add(20.0, 10.0)).andReturn(30.0);

to be read as "when calcService.add() is called with 20 and 10, give 30".

And at the end you:

  1. Test if your tested method returns what is expected - assertXXX()
  2. Test if the calcService has been used - verify()

Btw, the code

Assert.assertEquals(mathApplication.subtract(20.0, 10.0), 10.0, 0);

contains an error - look at the documentation. Correctly it should be

Assert.assertEquals(10.0, mathApplication.subtract(20.0, 10.0), 0);

It works almost the same, just you will get more proper error message if the test doesn't work:

Assertion error - expected 10.0, but was 11.0.

And anyway, it would be better readable if written as:

double expected = 30.0;
double actual = mathApplication.subtract(20.0, 10.0);
Assert.assertEquals(expected, actual, 0.0000000001); // never expect exact floating point result

And why you should interface: it's a good practice :) It's easier for the frameworks to mock an interface than a class (and some mock frameworks even cannot mock a class). And it leads you in learning to separate an interface from its implementation and write better testable classes.

Honza Zidek
  • 9,204
  • 4
  • 72
  • 118
  • really helpful man. i know what the code is. i just cant figure the injection part's out :\ . why we do that? – Wooopsa Aug 04 '15 at 11:08
  • So now you get it? :) Btw, read also about the proper usage of assert(). – Honza Zidek Aug 04 '15 at 11:29
  • i read about assert an other stuff in my code. but the injection, noo :( can you help me more? – Wooopsa Aug 04 '15 at 11:33
  • @Hamid Please see the two links in my answer: Spring Dependency Injection and JavaEE CDI. You may also search for more detailed explanation of dependency injection. I added some more explanation but for more you should use external sources. – Honza Zidek Aug 06 '15 at 09:32