我有一个- (void) keyboardUP:(NSNotification *)notification
{
NSDictionary* info = [notification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height + 10, 0.0);
_scroller.contentInset = contentInsets;
_scroller.scrollIndicatorInsets = contentInsets;
CGRect aRect = App_Delegate.window.frame;
aRect.size.height -= kbSize.height;
CGRect rect = [_activeField convertRect:_activeField.frame fromView:App_Delegate.window];
if (!CGRectContainsPoint(aRect, rect.origin) )
{
[_scroller scrollRectToVisible:rect animated:YES];
}
应用程序,其中spring-boot
初学者类看起来像标准类。所以我为我的所有功能创建了许多测试,并将摘要发送到sonarqube以查看我的报道。
对于我的初级班,Sonarqube告诉我,我只有60%的覆盖率。所以平均覆盖率并不如预期的那么好。
My Test类只是默认类。
@SpringBootApplication
那么如何在我的应用程序的入门类中测试我的主类呢?
答案 0 :(得分:31)
所有这些答案似乎都是矫枉过正的 您不需要添加测试来使度量工具满意 加载应用程序的Spring上下文需要时间。不要在每个开发人员构建中添加它只是为了赢得应用程序中大约0.1%的覆盖率 这里您不会只涵盖1个公共方法中的1个语句。它在应用程序的覆盖范围方面没有任何意义,其中通常会编写数千个语句。
第一种解决方法:使你的Spring Boot应用程序类内部没有声明bean。如果您有它们,请在配置类中移动它们(使它们仍然通过单元测试覆盖)。然后忽略test coverage configuration.
中的Spring Boot应用程序类第二种解决方法:如果你真的需要覆盖main()
调用(例如出于组织原因),请为它创建一个测试但是进行集成测试(由持续集成工具执行而不是在每个开发人员构建中执行)并清楚地记录测试类的目的:
import org.junit.Test;
// Test class added ONLY to cover main() invocation not covered by application tests.
public class MyApplicationIT {
@Test
public void main() {
MyApplication.main(new String[] {});
}
}
答案 1 :(得分:10)
你可以做这样的事情
@Test
public void applicationContextLoaded() {
}
@Test
public void applicationContextTest() {
mainApp.main(new String[] {});
}
答案 2 :(得分:4)
我有相同的目标(有一个运行main()方法的测试)我发现只需添加一个像@ fg78nc这样的测试方法,实际上就是#34; start"应用程序两次:一次是通过spring boot测试框架,一次是通过mainApp.main(new String[] {})
的显式调用,我找不到优雅。
我最后编写了两个测试类:一个带有@SpringBootTest
注释,另一个带有空测试方法 applicationContextLoaded(),另一个没有@SpringBootTest
(只有RunWith(SpringRunner.class)
)调用main方法。
<强> SpringBootApplicationTest 强>
package example;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootApplicationTest {
@Test
public void contextLoads() {
}
}
<强> ApplicationStartTest 强>
package example;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
public class ApplicationStartTest {
@Test
public void applicationStarts() {
ExampleApplication.main(new String[] {});
}
}
总的来说,应用程序仍然启动了两次,但因为现在有两个测试类。当然,仅使用这两种测试方法,似乎有些过分,但通常会使用SpringBootApplicationTest
设置将更多测试添加到课程@SpringBootTest
中。
答案 3 :(得分:2)
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>your.awesome.package.Application</mainClass>
</configuration>
</plugin>
如果您的目标是100%覆盖,那么您可以做的一件事就是根本没有主要方法。你仍然需要一个用@SpringBootApplication
注释的类,但它可以是空的。
请注意,因为它有其缺点,依赖main
的其他工具可能会中断。
答案 4 :(得分:1)
尽管已经广泛回答了这个问题,但我有一个用例在这里没有涉及,也许很有趣。我在启动时正在验证一些属性,我想断言,如果这些属性配置错误,则应用程序将无法启动。在JUnit4中,我可以做这样的事情:
@ActiveProfiles("incorrect")
@SpringBoot
public class NetworkProbeApplicationTest {
@Test(expected=ConfigurationPropertiesBindException.class)
public void contextShouldNotLoadWhenPropertiesIncorrect() {
}
}
但是在JUnit5中,您不能再将“ expected”值添加到@Test批注中,而必须做不同的事情。而且由于我想使用一组不正确的属性来启动应用程序,因此我需要传递要用作main()参数的配置文件。我在任何地方都找不到这个文档,但是通过main()方法传递参数需要您在参数前面加上双连字符,并用等号将键和值分开。完整的测试应如下所示:
import org.junit.jupiter.api.Test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesBindException;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class NetworkProbeApplicationTest {
@Test
public void contextShouldNotLoadWhenPropertiesIncorrect() {
Exception exception = assertThrows(ConfigurationPropertiesBindException.class, () -> {
SpringApplication.run(NetworkProbeApplication.class, "--spring.profiles.active=incorrect");
});
String expectedMessage = "Error creating bean with name 'dnsConfiguration': Could not bind properties to 'DnsConfiguration' : prefix=dns";
assertTrue(exception.getMessage().contains(expectedMessage));
}
}
答案 5 :(得分:0)
您可以模拟epoll_pwait
,因为这是被测方法的依赖项。了解如何here。
即
SpringApplication
答案 6 :(得分:0)
我在这里用另一种方式解决了。由于此方法仅是通向Spring运行的桥梁,因此我用@lombok.Generated
注释了该方法,现在声纳在计算测试覆盖率时将其忽略。
其他@Generated
注释,例如javax.annotation.processing.Generated
或javax.annotation.Generated
也可能有效,但由于签发证件已关闭,我现在无法测试。
package com.stackoverflow;
import lombok.Generated;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
@Generated
public static void main(String... args) {
SpringApplication.run(Application.class, args);
}
}
答案 7 :(得分:0)
这个针对SpringApplication的简单模拟测试不会调用任何方法,而只是测试入门应用程序。 [使用PowerMockRunner.class]
<html>
答案 8 :(得分:0)
除了上面的答案外,这是SpringBoot应用程序主要方法的单元测试,以供您使用JUnit 5:
try (MockedStatic<SpringApplication> mocked = mockStatic(SpringApplication.class)) {
mocked.when(() -> { SpringApplication.run(ElectronicGiftCardServiceApplication.class,
new String[] { "foo", "bar" }); })
.thenReturn(Mockito.mock(ConfigurableApplicationContext.class));
ElectronicGiftCardServiceApplication.main(new String[] { "foo", "bar" });
mocked.verify(() -> { SpringApplication.run(ElectronicGiftCardServiceApplication.class,
new String[] { "foo", "bar" }); });
}
当我们调用ElectronicGiftCardServiceApplication.main()时,它会验证SpringApplication类上的静态方法run()是使用预期的String数组调用的。
与awgtek和Ramji Sridaran想法相同,但是它们的解决方案适用于JUnit 4。