首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我如何伪装SpringApplication.run?

我如何伪装SpringApplication.run?
EN

Stack Overflow用户
提问于 2017-01-03 19:55:18
回答 3查看 5.9K关注 0票数 1

我有一个Spring批处理程序,我想测试它。

SpringApplication.run()是一个静态方法,我想验证传递给它的参数。

这是否意味着我需要沿着PowerMock路径走下去,还是SpringFramework中有什么东西可以让我测试它呢?

代码语言:javascript
复制
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;
}

我的测试类有以下注释,这些注释似乎不起作用:

代码语言:javascript
复制
@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批处理应用程序,所以没有web环境,我还添加了。

代码语言:javascript
复制
@SpringBootTest(webEnvironment=WebEnvironment.NONE)
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-01-05 00:43:23

这个问题是由于我在pom.xml中缺少一个条目而引起的异常,这使我对SpringFramework有点失望,因为我只在批处理应用程序中工作,并且在这个测试中没有任何web或servlet组件。丢失的pom条目是。

代码语言:javascript
复制
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
    </dependency>

其他的春天的依赖,我是

代码语言:javascript
复制
    <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来简化这个测试。下面是我的实现类以及测试它的测试类。

代码语言:javascript
复制
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;
    }
}

这是考试课

代码语言:javascript
复制
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
EN

Stack Overflow用户

发布于 2017-01-04 07:56:59

由于我和您一样不喜欢PowerMock,第一个答案是不幸的:您现在编写的方法-- yes,它只能使用PowerMock进行测试。

因此,如果要测试,则必须使用方法;必须使用PowerMock。或者你承担最小的风险..。别再测试了。

除此之外,我建议将该方法放到某些接口中;您只想防止这个静态调用在您开始测试其他想要调用handleFile()的方法时给您带来麻烦--然后您希望能够模拟该调用;防止内部发生静态调用。

票数 1
EN

Stack Overflow用户

发布于 2017-01-04 09:47:44

1.如果要在测试中验证args,则需要将其返回给方法handleFile(file)的调用方代码,当前正在执行- return null;,而应该返回args (如果方法签名可以更改)。

我假设handleFile方法在InitialFileBatchApplication类中。

代码语言:javascript
复制
@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中,因此,如果您可以重构代码,让一个非静态方法调用静态方法,那么您可以模拟非静态方法,这将最终模拟您的静态调用。@MockBean注释是Spring的一部分。

4.如果在春季批处理中模拟SpringApplication.run等价于,而不是运行作业,而是简单地初始化上下文,那么可以通过在application.properties中说spring.batch.job.enabled=false来达到目的。只有您的单元测试需要等待- SpringApplication.run的真正调用才能完成,但是作业不会开始。

除了功能正确之外,还鼓励代码重构使您的代码单元可测试,所以不要犹豫重构以克服框架限制。

希望能帮上忙!

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41451335

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档