2017-01-03 2 views
1

У меня есть обработчик файлов для Spring Batch, который я хочу проверить.Как сделать Mock SpringApplication.run

SpringApplication.run() - статический метод, для которого я хотел бы проверить переданные ему аргументы.

Означает ли это, что мне нужно спуститься по пути PowerMock или есть что-то в SpringFramework, которое позволит мне проверить это?

public File handleFile(File file) { 

    // Start the Batch Process and set the inputFile parameter 
    String[] args = {"--inputFile=" + file.getAbsolutePath()}; 
    SpringApplication.run(InitialFileBatchApplication.class, args); 

    return null; 
} 

Мой тестовый класс имеет следующие аннотации, которые не кажется ли работать:

@RunWith(PowerMockRunner.class) 
@PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class) 
@SpringBootTest 
@PrepareForTest(SpringApplication.class) 

Что мне не хватает?

Исключение получение выброшен является:

java.lang.IllegalStateException: Не удалось преобразовать класс с именем org.springframework.boot.SpringApplication. Причина: не может найти org.springframework.web.context.support.StandardServletEnvironment

Это происходит, когда @PrepareForTest(SpringApplication.class) обрабатывается. Я тестирую приложение Spring Batch, поэтому нет веб-среды, и я также добавил.

@SpringBootTest(webEnvironment=WebEnvironment.NONE) 

ответ

1

Эта проблема из-за исключения, которое я имел, была связана с отсутствующей записью в pom.xml, что немного расстраивает меня с помощью SpringFramework, поскольку я работаю только в пакетном приложении и не имею веб-сервлета или сервлета компонентов в этом тесте. Отсутствует запись pom.

<dependency> 
     <groupId>org.springframework</groupId> 
     <artifactId>spring-web</artifactId> 
    </dependency> 

Другие весенние dependecies, что у меня было были

<dependency> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-starter-batch</artifactId> 
    </dependency> 

    <dependency> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-starter-test</artifactId> 
     <scope>test</scope> 
    </dependency> 

Чтобы проверить это, я беру подход PowerMock с экстернализующими некоторые из методов, чтобы я мог проверить их, и несмотря на то, Я тестирую приложение Spring, я смог исключить SpringRunner, который загружает контекст, чтобы упростить этот тест. Ниже приведен мой класс реализации, а также тестируемый класс.

import java.io.File; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
import org.springframework.boot.SpringApplication; 

public class InitialFileInputFileHandler { 

    private Logger logger = LoggerFactory.getLogger(InitialFileInputFileHandler.class); 

    /** 
    * Handles the Initial Client files that get put into the input directory that match the pattern 
    * defined in initialFileListenerApplicationContext.xml 
    * @param file - The file 
    * @return 
    */ 

    public File handleFile(File file) { 

     logger.info("Got the Initial Client file: " + file.getAbsolutePath() + " start Batch Processing"); 

     // Start the Batch Process and set the inputFile parameter 
     String[] args = buildArguments(file); 

     SpringApplication.run(InitialFileBatchApplication.class, args); 

     // Whatever we return is written to the outbound-channel-adapter. 
     // Returning null will not write anything out and we do not need an outbound-channel-adapter 
     return null; 
    } 

    protected String[] buildArguments(File file) { 
    String[] args = {"--inputFile=" + file.getAbsolutePath()}; 
    return args; 
    } 
} 

А вот тестовый класс

import static org.mockito.Mockito.*; 
import static org.hamcrest.Matchers.*; 
import static org.hamcrest.MatcherAssert.*; 

import java.io.File; 

import org.junit.Before; 
import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.mockito.Mock; 
import org.mockito.Mockito; 
import org.powermock.api.mockito.PowerMockito; 
import org.powermock.core.classloader.annotations.PrepareForTest; 
import org.powermock.modules.junit4.PowerMockRunner; 
import org.springframework.boot.SpringApplication; 

// This test class must test static methods. One way to do that is with PowerMock. 

// Testing with static methods so we have to run with the PowerMockRunner. 
@RunWith(PowerMockRunner.class) 
// The static method that we want to test is in the SpringApplication class so 
// by using PowerMock we have to prepare this class for testing. 
@PrepareForTest({SpringApplication.class}) 

// If you wanted to load a SpringContext you'd have to include the SpringRunner. 
// Since our Runner is PowerMockRunner, we still have to setup the spring context, so 
// you setup the SpringRunner as the delegate. 
//@PowerMockRunnerDelegate(SpringRunner.class) 
public class InitialFileInputFileHandlerTest { 

    // Setup a mockFile so that I can specify what comes back from the getAbsolutiePath method 
    // without actually to have a file on the file system. 
    @Mock File mockFile; 

    private InitialFileInputFileHandler handler; 

    @Before 
    public void setUp() throws Exception { 
    handler = new InitialFileInputFileHandler(); 
    org.mockito.Mockito.when(mockFile.getAbsolutePath()).thenReturn("src/input/fooFile.txt"); 
    } 

    @Test 
    public void testBuildArguments(){ 
    String[] args = handler.buildArguments(mockFile); 
    assertThat(args[0], equalTo("--inputFile=src/input/fooFile.txt")); 
    } 

    @Test 
    public void testHandleFile() throws Exception { 
    // Tell PowerMockito to keep track of my static method calls in the SpringApplication class 
    PowerMockito.mockStatic(SpringApplication.class); 

    // What I expect the argument to be 
    String[] args = {"--inputFile=src/input/fooFile.txt"}; 

    // Call the actual method 
    handler.handleFile(mockFile); 

    // Have to call verifyStatic since its a static method. 
    PowerMockito.verifyStatic(); 

    // One of a few possibilities to test the execution of the static method. 
    //SpringApplication.run(InitialFileBatchApplication.class, args); 
    //SpringApplication.run(Mockito.any(InitialFileBatchApplication.class), eq(args[0])); 
    SpringApplication.run(Mockito.any(Object.class), eq(args[0])); 
    } 

} 
1

Как я разделяю вашу нелюбовь к PowerMock, первый ответ, к сожалению: метод, который вы написали прямо сейчас - да, которые могут быть проверены только с помощью PowerMock.

Итак, если вы хотите проверить что метод; вы должны использовать PowerMock. Или вы берете минимальный риск ... и просто не проверяете его.

Помимо этого: я рекомендую поместить этот метод в некоторый интерфейс; вы просто хотите, чтобы предотвращал, что этот статический вызов дает вам проблемы при запуске тестирования других методов, которые хотят вызвать handleFile(), - тогда вы хотите быть в состоянии издеваться над этим вызовом; чтобы предотвратить статический вызов внутри.

0

1.Если вы хотите проверить args в тестах, вы должны вернуть его к абоненту код метода handleFile(file) и в настоящее время вы делаете - return null;, вместо этого вы должны вернуться арг (если метод подписи может быть изменен).

Я предположил, что handleFile способ в InitialFileBatchApplication класс.

@Test 
    public void testHandleFile() { 
     File file = new File("ABC"); 
     String[] response = new InitialFileBatchApplication().handleFile(file); 

     //Verify response here 
    } 

Над вами фактически начнется ваша работа.

2.Если вы хотите высмеять - SpringApplication.run как есть, PowerMock - это путь. Вы должны указать на вопрос, какую ошибку вы получаете с текущей настройкой.

3.Mockito встроен в Spring Test, поэтому, если вы можете реорганизовать свой код, чтобы нестатический метод вызывал статический метод, вы можете высмеять нестатический метод и в конечном итоге издеваются над вашим статическим вызовом. @MockBean аннотация является частью теста весны.

4.Если Mocking SpringApplication.run весной партии эквивалентно не работает на работу а просто инициализирует контекст, то цель может быть достигнута путем говорить, spring.batch.job.enabled=false в application.properties. Только то, что ваши юнит-тесты должны будут дождаться реального звонка - SpringApplication.run, но работа не начнется.

Рефакторинг кода всегда рекомендуется сделать ваш блок кода проверяемым в дополнение к функциональному правилу, поэтому не стесняйтесь рефакторировать, чтобы преодолеть рамки ограничений.

Надеюсь, это поможет!

+0

Idealling насмешливого SpringApplication.run является то, что я хочу сделать, но это не значит, что я должен быть architecturing этого класса по-разному, так что его проверяемое. Из моего тестового класса теперь у меня есть следующие аннотации, но все еще получаю исключение выше. @RunWith (PowerMockRunner.class) @PowerMockRunnerDelegate (SpringRunner.class) @PrepareForTest (SpringApplication.class) @SpringBootTest (webEnvironment = WebEnvironment.NONE) @TestPropertySource (свойства = { "spring.batch.job.enabled = ложь "}) –

Смежные вопросы