我有一个Spring-Boot应用程序,其中默认属性设置在application.properties类路径中的文件中(src/main/resources/application.properties).
我想在我的JUnit测试中覆盖一些默认设置,其中包含在test.properties文件中声明的属性(src/test/resources/test.properties)
我通常会为我的Junit测试提供专用的Config类,例如
package foo.bar.test;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@Import(CoreConfig.class)
@EnableAutoConfiguration
public class TestConfig {
}
Run Code Online (Sandbox Code Playgroud)
我首先想到@PropertySource("classpath:test.properties")在TestConfig类中使用可以解决这个问题,但这些属性不会覆盖application.properties设置(请参阅Spring-Boot参考文档 - 23.外部化配置).
然后我尝试-Dspring.config.location=classpath:test.properties在调用测试时使用.这很成功 - 但我不想为每次测试执行设置此系统属性.因此我把它放在代码中
@Configuration
@Import(CoreConfig.class)
@EnableAutoConfiguration
public class TestConfig {
static {
System.setProperty("spring.config.location", "classpath:test.properties");
}
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,再次没有成功.
必须有一个关于如何application.properties在JUnit测试中覆盖设置的简单解决方案test.properties,我必须忽略它.
我们假设我有以下方法应该测试:
@Autowired
private RoutingService routingservice;
public void methodToBeTested() {
Object objectToRoute = initializeObjectToRoute();
if (someConditions) {
routingService.routeInOneWay(objectToRoute);
} else {
routingService.routeInAnotherWay(objectToRoute);
}
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下RoutingService,在单独的线程中运行,因此在它的构造函数中我们有以下内容:
Thread thread = new Thread(this);
thread.setDaemon(true);
thread.start();
Run Code Online (Sandbox Code Playgroud)
问题是RoutingService改变状态,objectToRoute这正是我想要检查的,但这不会立即发生,因此测试失败.但是,如果我添加Thread.sleep()然后它可以工作,但这是不好的做法,因为我知道.
Thread.sleep()在这种情况下我该如何避免?
我正在努力解决 PATCH 方法的最佳实践是什么。
我看到了几种可能性:
200 OK。204 No Content。最好的是什么?
我有一个静态方法的类,我目前正在使用JMockit进行模拟.说它看起来像:
public class Foo {
public static FooValue getValue(Object something) {
...
}
public static enum FooValue { X, Y, Z, ...; }
}
Run Code Online (Sandbox Code Playgroud)
我有另一个类(让我们称之为MyClass)调用Foo的静态方法; 我正在尝试为这个类编写测试用例.我的JUnit测试,使用JMockit,看起来像这样:
public class MyClassTest extends TestCase {
@NonStrict private final Foo mock = null;
@Test public void testMyClass() {
new Expectations() {
{
Foo.getValue((Object) any); result = Foo.FooValue.X;
}
};
}
myClass.doSomething();
}
Run Code Online (Sandbox Code Playgroud)
这工作正常,花花公子,当测试执行时,我的MyClass实例将在调用Foo.getValue()时正确获取Foo.FooValue.X的枚举值.
现在,我正在尝试迭代枚举中的所有值,并重复运行测试.如果我将上面的测试代码放在for循环中并尝试将模拟静态方法的结果设置为每个枚举值,那么这不起作用.Foo.getValue()的模拟版本总是返回Foo.FooValue.X,并且在迭代枚举时从不返回任何其他值.
如何在单个JUnit测试中多次模拟静态方法?我想做这样的事情(但显然它不起作用):
public class MyClassTest extends TestCase {
@NonStrict private final Foo mock = null;
@Test public void testMyClass() …Run Code Online (Sandbox Code Playgroud) 我正在尝试为Intellij IDEA开发一个插件,我正在使用SDK 129.451.
我遇到的问题是,我不能像在插件中输入的一些列表项一样保留用户数据,并在IDE重新启动后恢复数据.
我使用PersistentStateComponent来持久保存数据,这个getState()方法似乎被调用但loadState()方法却没有.
这是一个扩展PersistentStateComponent的示例类:
@State(name = "Test", storages = {@Storage(file = StoragePathMacros.APP_CONFIG+"/other.xml"
)})
public class Test implements PersistentStateComponent<Element> {
String ceva;
public Test() {
ceva = "sad";
System.out.println("constr");
}
public String getCeva() {
return ceva;
}
public void setCeva(String ceva) {
this.ceva = ceva;
}
public void loadState(Element state) {
System.out.println("cstate load");
ceva = (String) state.getContent().get(0);
}
public Element getState() {
System.out.println("cstate retu");
Element configurationsElement = new Element("testtt");
configurationsElement.addContent(ceva);
return configurationsElement;
}
}
Run Code Online (Sandbox Code Playgroud)
我还在plugin.xml中添加了这个类: …
如果我为一个抛出一堆异常的函数编写测试用例,我应该在我的测试方法中为这些异常添加一个throws声明,还是应该捕获每个异常.这是怎样的正确方法?我相信try-catch是一种更好的方法,但是在catch块中我应该打印堆栈跟踪吗?
例如,我有一个getGroups(String name)抛出的方法AuthenticationException.如果我编写一个测试用例来检查IllegalArgumentException当name参数为null 时是否抛出了一个,我该如何处理AuthenticationException?我是否将它添加到抛出我方法的一部分,或者我应该将异常包含在一个try-catch块中.
@Test
public void testGetGroupsWithNull() throws AuthenticationException {
thrown.expect(IllegalArgumentException.class);
getGroups(null);
}
Run Code Online (Sandbox Code Playgroud)
在上面的测试用例中我刚添加了一个throws AuthenticationException,但是我想知道是否最好将异常包含在try-catch块中以及在捕获异常后我做了什么.我可以打印堆栈跟踪.
我AuthenticationException通过不将它放在'throws'子句中而是放在try/catch块中来处理意外异常.
@Test
public void testGetGroupsWithNull() {
thrown.expect(IllegalArgumentException.class);
try {
getGroups(null);
} catch(AuthenticationExcption e) {
Assert.fail("Authentication Exception");
}
}
Run Code Online (Sandbox Code Playgroud) 假设我的 Log4j2 xml 配置类似于
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Properties>
<Property name="company.log.folder">.</Property>
</Properties>
<Appenders>
<RollingFile name="mainFile" fileName="${sys:company.log.folder}/main.log"
filePattern="archive-logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.zip">
<PatternLayout>
<Pattern>%d [%t] %-5p %c - %m%n</Pattern>
</PatternLayout>
<Policies>
<SizeBasedTriggeringPolicy size="10MB"/>
</Policies>
</RollingFile>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="mainFile"/>
</Root>
</Loggers>
</Configuration>
Run Code Online (Sandbox Code Playgroud)
我主要对这里的两个参数感兴趣 -级别和大小。那么,如果我写INFO而不是info或者10mb而不是10MB有什么区别吗?其他参数呢?
我有一些业务逻辑类:
public class SomeService {
public void doFirst() {}
public void doSecond() {
doFirst();
}
}
Run Code Online (Sandbox Code Playgroud)
并测试它:
public class SomeServiceTest {
private SomeService service;
@Before
public void setUp() {
service = new SomeService();
}
@Test
public void doSecond_someCondition_shouldCallFirst() {
// given
...
// when
service.doSecond();
//then
how to verify doFirst() was called?
}
}
Run Code Online (Sandbox Code Playgroud)
如何验证doFirst()不是在模拟上调用,而是在实际服务中调用?
假设我想benchmark为该类编写一个autowired,因此我需要加载application context.
我的测试有注释@org.openjdk.jmh.annotations.State(Scope.Benchmark)和主要方法
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(MyBenchmark.class.getSimpleName())
.forks(1)
.build();
new Runner(opt).run();
}
Run Code Online (Sandbox Code Playgroud)
当然,我有一些这样的基准:
@Benchmark
public void countAllObjects() {
Assert.assertEquals(OBJECT_COUNT, myAutowiredService.count());
}
Run Code Online (Sandbox Code Playgroud)
现在的问题是如何注入myAutowiredService?
可能的解决方案
在方法中手动加载上下文@Setup。
ApplicationContext context = new ClassPathXmlApplicationContext("META-INF/application-context.xml");
context.getAutowireCapableBeanFactory().autowireBean(this);
Run Code Online (Sandbox Code Playgroud)
但我不喜欢这个解决方案。我希望我的测试只有注释
@ContextConfiguration(locations = { "classpath:META-INF/application-context.xml" })
Run Code Online (Sandbox Code Playgroud)
然后我就注入我的豆子
@Autowired
private MyAutowiredService myAutowiredService;
Run Code Online (Sandbox Code Playgroud)
但这不起作用。我认为原因是我没有注释表明我的测试应该使用 Spring 运行:
@RunWith(SpringJUnit4ClassRunner.class)
Run Code Online (Sandbox Code Playgroud)
然而这样做是没有意义的,因为我也没有任何@Test带注释的方法,因此我会得到No runnable methods异常。
在这种情况下我可以通过注释实现加载上下文吗?
试图收集和理解@Transactional注解的要点,并跨越了一个点。因此,在使用 Transactional 注释时,我们需要记住的主要事项是:
不幸的是,我没有找到这个问题的答案:最好将事务注释放在类还是方法中?我们可以考虑不同的情况,但我最感兴趣的是当我们有几种方法必须有这个注释而有些方法没有时。
另外,也许您想在此列表中添加一些要点,那真的很棒。
java ×8
junit ×4
unit-testing ×3
spring ×2
annotations ×1
exception ×1
jmockit ×1
junit4 ×1
log4j ×1
log4j2 ×1
logging ×1
methods ×1
mockito ×1
patch ×1
persistence ×1
plugins ×1
resources ×1
rest ×1
spring-boot ×1
spring-mvc ×1
static ×1
tdd ×1
transactions ×1
web-services ×1
xml ×1