我有一个Spring批处理程序,我想测试它。
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批处理应用程序,所以没有web环境,我还添加了。
@SpringBootTest(webEnvironment=WebEnvironment.NONE)发布于 2017-01-05 00:43:23
这个问题是由于我在pom.xml中缺少一个条目而引起的异常,这使我对SpringFramework有点失望,因为我只在批处理应用程序中工作,并且在这个测试中没有任何web或servlet组件。丢失的pom条目是。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>其他的春天的依赖,我是
<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]));
}
}发布于 2017-01-04 07:56:59
由于我和您一样不喜欢PowerMock,第一个答案是不幸的:您现在编写的方法-- yes,它只能使用PowerMock进行测试。
因此,如果要测试,则必须使用方法;必须使用PowerMock。或者你承担最小的风险..。别再测试了。
除此之外,我建议将该方法放到某些接口中;您只想防止这个静态调用在您开始测试其他想要调用handleFile()的方法时给您带来麻烦--然后您希望能够模拟该调用;防止内部发生静态调用。
发布于 2017-01-04 09:47:44
1.如果要在测试中验证args,则需要将其返回给方法handleFile(file)的调用方代码,当前正在执行- return null;,而应该返回args (如果方法签名可以更改)。
我假设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中,因此,如果您可以重构代码,让一个非静态方法调用静态方法,那么您可以模拟非静态方法,这将最终模拟您的静态调用。@MockBean注释是Spring的一部分。
4.如果在春季批处理中模拟SpringApplication.run等价于,而不是运行作业,而是简单地初始化上下文,那么可以通过在application.properties中说spring.batch.job.enabled=false来达到目的。只有您的单元测试需要等待- SpringApplication.run的真正调用才能完成,但是作业不会开始。
除了功能正确之外,还鼓励代码重构使您的代码单元可测试,所以不要犹豫重构以克服框架限制。
希望能帮上忙!
https://stackoverflow.com/questions/41451335
复制相似问题