Тестирование интерфейса или класса? - PullRequest
0 голосов
/ 22 мая 2018

Я новичок в Java, и я запутался в тестировании кода с помощью JUnit и Mockito.

Я разработал проект на github, где задача состоит в том, чтобы написать тестирование Junit для AccountService, которое являетсяинтерфейс.Что я не знаю, что я должен проверить?Интерфейс или класс, который реализует интерфейс?

Вот AccountService:

public interface AccountService {
    public Operation deposit(String accountNumber, int amount);
    public Operation withdraw(String accountNumber, int amount);
    public OperationsDto history(String accountNumber);
}

Вот AccountService реализация

@Service
public class AccountServiceImpl implements  AccountService {

    @Autowired
    private AccountRepository accountRepository;
    @Autowired
    private OperationRepository operationRepository;

    @Autowired
    OperationConverter operationConverter;


    public Operation deposit(String accountNumber, int amount) {
        checkAmount (amount);

        AccountEntity account = getAccount (accountNumber);

        int balance =  account.getBalance();
        balance = balance + amount;

        OperationEntity operation = new OperationEntity();
        operation.setAccount(accountNumber);
        operation.setAmount(amount);
        operation.setType(OperationType.DEPOSIT.toString());
        operation.setDate(DateUtil.getCurrentDate());
        operation.setBalance(balance);

        operationRepository.save(operation);

        //update account balance
        account.setBalance(balance);
        accountRepository.save(account);

        return  operationConverter.convert(operation);
    }

    public Operation withdraw(String accountNumber, int amount) {
        checkAmount (amount);

        AccountEntity account = getAccount (accountNumber);

        int balance = account.getBalance();
        balance = balance - amount;
        if(balance < 0){
            throw new OperationException(Constants.ERROR_INVALID_OPERATION);
        }

        OperationEntity operation = new OperationEntity();
        operation.setBalance(balance);
        operation.setAccount(accountNumber);
        operation.setAmount(amount);
        operation.setType(OperationType.WITHDRAW.toString());
        operation.setDate(DateUtil.getCurrentDate());

        operationRepository.save(operation);

        //update account balance
        account.setBalance(balance);
        accountRepository.save(account);

        return  operationConverter.convert(operation);
    }

    public OperationsDto history(String accountNumber) {
        List<OperationEntity>  operations = 
        operationRepository.findByAccount(accountNumber);
        return operationConverter.convertList(operations);
    }

    private AccountEntity getAccount(String accountNumber){

        AccountEntity account = 
        accountRepository.findByNumber(accountNumber);

        if(account == null) {
            throw new AccountException(Constants.ERROR_INVALID_ACCOUNT);
        }

        return account;
    }

    private void checkAmount (int amount) {
        if(amount < 0){
            throw new OperationException(Constants.ERROR_INVALID_OPERATION);
        }
    }
}

1 Ответ

0 голосов
/ 22 мая 2018

Вы должны проверить реализацию, следовательно, класс.

Интерфейс следует использовать только для инъекций.Итак, взглянув на код, который вы разместили, вы должны проверить класс AccountServiceImpl в классе AccountServiceImplTest (или что-то подобное).

В этом модульном тесте вы должны высмеивать AccountRepository, OperationRepositoryи OperationConverter.В тестовом модуле вы должны тестировать только тот класс, который заинтересован в тестировании, а не его зависимости.Итак, вы вводите интерфейсы, используя @Autowired.Таким образом, используя фиктивный фреймворк, вы можете смоделировать ваши классовые зависимости, изолируя модуль, который вам нужен тест.

Посмотрите на класс, который вы опубликовали: вы вводите три компонента с помощью аннотации.Я уверен, что все эти типы интерфейсов.При развертывании приложения Spring CDI позаботится о внедрении реальных реализаций сразу после запуска контейнера (или правильного запуска Spring Boot).Когда вы запускаете этот класс, вы хотите изолировать его.Тест должен быть как можно более атомарным.Используя Mockito вместе с правильным бегуном JUnit, вы предоставите ложную реализацию для внедренных bean-компонентов.Используя Mockito API, вы можете сказать, как эта ложная реализация должна отвечать на определенный запрос.Итак, вы берете реализацию AccountServiceImpl, смоделируете все ее зависимости и затем тестируете только логику, содержащуюся в этом классе.Вы не тестируете интерфейс, потому что интерфейс представляет собой только контракт для вызова сервиса, а не его реализацию.

@RunWith(MockitoJUnitRunner.class)
public class AccountServiceTest {

@Mock
private AccountRepository accountRepository;

@Mock
private OperationRepository operationRepository;

@Mock
OperationConverter operationConverter;

@InjectMocks
private AccountServiceImpl accountService;

@Before
public void setUp() {
    /* here goes before-class init logic */
}

@Test
public void testMethod1() {
    /* here you test a method*/
}

@Test
public void testMethod2() {
    /* here you test another method*/
}
}

Так должен выглядеть ваш тестовый класс.

...