我正在用JUnit5测试一个应用程序,并使用Jacoco进行报道。测试执行正常,并有测试报告。
但是,如果服务包含方法,则Jacoco report会有以下日志,并用@Transactional注释
[ant:jacocoReport] Classes in bundle 'my-service' do no match with execution data. For report generation the same class files must be used as at runtime.
[ant:jacocoReport] Execution data for class mypackage/SampleService does not match.
所有@Service class方法都会发生此错误,并用@Transactional注释,普通类coverage is calculated ok。
下面是一个样本测试:
@SpringBootTest
@ExtendWith(SpringExtension.class)
public class MyServiceTest {
@Autowired
private SampleService sampleService;
@Test
public void doWork(){
sampleService.doWork();
}
}
很好。覆盖率为非零:
public class SampleService {
public void doWork(){
System.out.println("HEY");
}
}
0%覆盖率:
public class SampleService {
@Transactional
public void doWork(){
System.out.println("HEY");
}
}
Transactional围绕actuall类创建一个代理。但是,难道雅科科没有现成的方法来处理这种常见的情况吗?
我已经尝试了@EnableAsheJAutoProxy与不同的标志变化,检查了最新的木星引擎和Jacoco插件使用
下面是gradle配置:
subprojects {
test {
useJUnitPlatform()
}
jacocoTestReport {
afterEvaluate {
classDirectories.from = files(classDirectories.files.collect {
fileTree(dir: it, exclude: '*Test.java')
})
}
reports {
html.enabled = true
xml.enabled = true
csv.enabled = false
}
}
}
感谢任何帮助
基于单模块检测示例https://stackoverflow.com/a/31916686/7096763(以及@MikaelF更新的gradle 5版本),下面是多模块检测示例:
subprojects { subproject ->
subproject.ext.jacocoOfflineSourceSets = [ 'main' ]
task doJacocoOfflineInstrumentation(dependsOn: [ classes, subproject.configurations.jacocoAnt ]) {
inputs.files classes.outputs.files
File outputDir = new File(subproject.buildDir, 'instrumentedClasses')
outputs.dir outputDir
doFirst {
project.delete(outputDir)
ant.taskdef(
resource: 'org/jacoco/ant/antlib.xml',
classpath: subproject.configurations.jacocoAnt.asPath,
uri: 'jacoco'
)
def instrumented = false
jacocoOfflineSourceSets.each { sourceSetName ->
if (file(sourceSets[sourceSetName].output.classesDirs[0]).exists()) {
def instrumentedClassedDir = "${outputDir}/${sourceSetName}"
ant.'jacoco:instrument'(destdir: instrumentedClassedDir) {
fileset(dir: sourceSets[sourceSetName].output.classesDirs[0], includes: '**/*.class')
}
//Replace the classes dir in the test classpath with the instrumented one
sourceSets.test.runtimeClasspath -= files(sourceSets[sourceSetName].output.classesDirs[0])
sourceSets.test.runtimeClasspath += files(instrumentedClassedDir)
instrumented = true
}
}
if (instrumented) {
//Disable class verification based on https://github.com/jayway/powermock/issues/375
test.jvmArgs += '-noverify'
}
}
}
test.dependsOn doJacocoOfflineInstrumentation
}
完整示例如下:https://github.com/lizardeye/jacocomultimodulesample
不过,我认为这是一个durty黑客攻击,可以很容易地用gradle或jacoco更新来破解
我尝试了一个测试项目,类似于你所描述的,但是我不能重现这个问题。我看到你的项目和我的项目之间唯一的区别是,我使用了maven而不是gradle。
以下是测试项目:https://github.com/gybandi/jacocotest
如果这对你没有帮助,你能把你的测试项目上传到github或其他地方吗?
编辑:@MikaelF发布了另一个答案的链接,显示了如何为jacoco添加离线检测。
在我添加了下面的块来构建之后,这里描述的解决方案对我来说很有效。格雷德尔:
task instrument(dependsOn: [classes, project.configurations.jacocoAnt]) {
inputs.files classes.outputs.files
File outputDir = new File(project.buildDir, 'instrumentedClasses')
outputs.dir outputDir
doFirst {
project.delete(outputDir)
ant.taskdef(
resource: 'org/jacoco/ant/antlib.xml',
classpath: project.configurations.jacocoAnt.asPath,
uri: 'jacoco'
)
def instrumented = false
if (file(sourceSets.main.java.outputDir).exists()) {
def instrumentedClassedDir = "${outputDir}/${sourceSets.main.java}"
ant.'jacoco:instrument'(destdir: instrumentedClassedDir) {
filehtml" target="_blank">set(dir: sourceSets.main.java.outputDir, includes: '**/*.class')
}
//Replace the classes dir in the test classpath with the instrumented one
sourceSets.test.runtimeClasspath -= files(sourceSets.main.java.outputDir)
sourceSets.test.runtimeClasspath += files(instrumentedClassedDir)
instrumented = true
}
if (instrumented) {
//Disable class verification based on https://github.com/jayway/powermock/issues/375
test.jvmArgs += '-noverify'
}
}
}
test.dependsOn instrument
jacoco插件的github上似乎也有关于这一点的公开信息:https://github.com/gradle/gradle/issues/2429
我正在使用Jacoco使用ANT查找单元测试的代码覆盖率,但报告没有生成,我得到了这个错误序列: 我已经阅读了这些答案,但似乎没有一个可以帮助我解决问题。 Jacoco代码覆盖报告生成器显示错误:“捆绑包‘代码覆盖报告’中的类与执行数据不匹配” jacoco:对于报告生成,必须使用与运行时相同的类文件 我在Eclipse上编译了所有类,并使用ANT构建工具对这些类执行代码覆盖。由于一些依赖关系,我
我在应用程序中工作。流程和往常一样:。 我用注释了服务层类,从而将该类中的每个方法都标记为事务性的。在服务类中,我调用以获取某个域对象,然后将其转换为对象,该对象将传递给Controller。为了将域对象转换为,我编写了另一个自定义静态类(只有静态方法的类),如,它将进行此转换。 现在,域对象有一些子对象(),它被懒洋洋地加载。因此,当我在中访问子getter方法时,会发出一个额外的数据库调用,该
试图收集和理解@事务性注释的要点并越过了一点。因此,在使用事务性注释时,我们需要记住的主要事情是: 事务注释只能应用于公共方法[根据Spring@Transactional属性对私有方法起作用吗? 事务性注释应该应用于具体的类,而不是接口[根据我应该将@transactional annotation放在接口定义还是实现类的位置? 事务注释应应用于服务级别[根据Spring@Transaction
当运行此操作时,可以看到批处理仍被打印为。我在设置交互时做错了什么?
问题内容: 我有一个用@Transactional注释的方法。我从Oracle数据库检索一个对象,更改一个字段,然后从该方法返回。我忘了保存对象,但是发现无论如何都会更新数据库。 applicationContext 我的方法 我的问题是为什么MyObject会持久保存到数据库? 问题答案: 因为hibernate将自动检测对持久实体所做的更改并相应地更新数据库。hibernate参考手册的第11