Модульный тест службы загрузки Spring с закрытыми полями и @PostConstruct - PullRequest
0 голосов
/ 16 октября 2018

У меня есть служба загрузки Spring, определенная следующим образом:

@Service
public class MyService {
    private String field1;
    private String field2;

    @Autowired
    private AnotherService anotherService

    @PostConstruct
    public void init() {
        anotherService.initField1(field1);
        anotherService.initField2(field2);
    }

    public String foo() {
        return field1 + field2;
    }
}

Как мне написать модульный тест для foo.Что ж, это больше о том, как работать с полями класса и методами PostConstruct.

Спасибо !!

РЕДАКТИРОВАТЬ: Добавлено AnotherService в качестве поля.

Ответы [ 2 ]

0 голосов
/ 16 октября 2018

Написание хорошего, тестируемого кода может быть трудным.Есть некоторые подводные камни, ожидающие того, что каждый рано или поздно попадет в него.

Как правило, старайтесь избегать внедрения на уровне поля, вместо этого используйте параметр конструктора:

@Service
public class MyService {

    private AnotherService anotherService;

    @Autowired
    MyService (AnotherService anotherService) {
         this.anotherService = anotherService;
    }

}

Этосамое чистое решение.Вы можете вызывать конструктор из ваших тестов, Spring будет вставлять зависимости таким же образом во время выполнения.Таким образом, нет никакой разницы, с которой нужно иметь дело.

То же самое относится к любым конструкциям жизненного цикла, таким как @PostConstruct.Если вы можете избежать их, сделайте это.Пусть конструктор справится с этим.Если вам абсолютно необходимо их хранить, то единственное логическое решение - вручную вызвать их из тестового кода.

Теперь, как настроить службы, которые во время выполнения будут автоматически подключаться контейнером?

Для модульного тестирования у вас в основном есть три варианта (в произвольном порядке):

  1. Если требуемый сервис довольно прост и его легко построить, создайте и передайте его какФреймворк будет делать.

  2. Если служба имеет ограниченный интерфейс, который меняется не слишком часто, создайте поддельный сервис.

  3. Используйте насмешкуlib like mockito (spring-boot-test предоставляет его по умолчанию).

0 голосов
/ 16 октября 2018

В следующем примере показан компонент @Service, который использует инжекцию конструктора для получения требуемого компонента AnotherService:

@Service
public class MyService {
    private String field1;
    private String field2;

    private final AnotherService anotherService;

    public MyService(AnotherService anotherService) {
        this.anotherService = anotherService;
        this.anotherService.initField1(field1);
        this.anotherService.initField2(field2);
    }

    public String foo() {
        return field1 + field2;
    }
}

Обратите внимание, что вы можете опустить @Autowired, потому что MyService имеет один конструктор.См. здесь для получения дополнительной информации.

тестирование с помощью Spring
Используйте @ RunWith ( SpringRunner.class ) и @ SpringBootTest для введения MyService и начала его использования:

@RunWith(SpringRunner.class)
@SpringBootTest
public class MyServiceTest {
    @Autowired    
    private MyService service;

    @Test
    public void testFoo() {
        String expResult = "";
        String result = service.foo();
        assertEquals(expResult, result);
    }
}

тестирование без Spring

public class MyServiceTest2 {
    private MyService service;

    @Before
    public void setUp() {
        service = new MyService(new AnotherService.Fake());
    }

    @Test
    public void testFoo() {
        String expResult = "";
        String result = service.foo();
        assertEquals(expResult, result);
    }
}

Здесь Fake является поддельной реализацией интерфейса AnotherService, которая позволяет вам провести чистый модульный тест.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...