Skip to content

Commit 568c9fb

Browse files
committed
Work in progress
1 parent 8cfd494 commit 568c9fb

10 files changed

Lines changed: 287 additions & 0 deletions

File tree

settings.gradle.kts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,7 @@ if (goIde.split(",").contains(ideType)) {
7373
include("utbot-spring-analyzer")
7474
include("utbot-spring-commons")
7575
include("utbot-spring-commons-api")
76+
77+
include("utbot-spring-sample")
78+
include("utbot-spring-test")
79+

utbot-framework-test/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ dependencies {
88

99
implementation(project(":utbot-framework"))
1010
testImplementation project(':utbot-sample')
11+
testImplementation project(':utbot-spring-sample')
1112
testImplementation project(":utbot-framework").sourceSets.test.output
1213
testImplementation project(":utbot-core").sourceSets.test.output
1314

utbot-spring-sample/build.gradle

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
plugins {
2+
id 'java-library'
3+
}
4+
5+
dependencies {
6+
implementation(project(":utbot-api"))
7+
8+
implementation 'org.projectlombok:lombok:1.18.20'
9+
annotationProcessor 'org.projectlombok:lombok:1.18.20'
10+
11+
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: springBootVersion
12+
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa', version: springBootVersion
13+
}
14+
15+
configurations {
16+
all {
17+
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
18+
}
19+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package org.utbot.examples.spring.autowiring;
2+
3+
import lombok.*;
4+
import lombok.extern.jackson.Jacksonized;
5+
6+
import javax.persistence.*;
7+
8+
@Getter
9+
@Setter
10+
@Builder
11+
@ToString
12+
@Jacksonized
13+
@NoArgsConstructor
14+
@AllArgsConstructor
15+
@Entity
16+
@Table(name = "orders")
17+
public class Order {
18+
@Id
19+
@GeneratedValue(strategy = GenerationType.IDENTITY)
20+
Long id;
21+
String buyer;
22+
Double price;
23+
int qty;
24+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package org.utbot.examples.spring.autowiring;
2+
3+
import org.springframework.data.jpa.repository.JpaRepository;
4+
5+
public interface OrderRepository extends JpaRepository<Order, Long> {
6+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package org.utbot.examples.spring.autowiring;
2+
3+
import org.springframework.beans.factory.annotation.Autowired;
4+
import org.springframework.stereotype.Service;
5+
6+
import java.util.List;
7+
8+
@Service
9+
public class OrderService {
10+
11+
@Autowired
12+
private OrderRepository orderRepository;
13+
14+
public List<Order> getOrders() {
15+
return orderRepository.findAll();
16+
}
17+
18+
public Order createOrder(Order order) {
19+
return orderRepository.save(order);
20+
}
21+
}

utbot-spring-test/build.gradle

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
dependencies {
2+
api project(':utbot-framework-api')
3+
implementation(project(":utbot-framework"))
4+
5+
testImplementation project(':utbot-testing')
6+
testImplementation project(':utbot-spring-sample')
7+
testImplementation project(":utbot-framework").sourceSets.test.output
8+
testImplementation project(":utbot-core").sourceSets.test.output
9+
10+
// To use JUnit4, comment out JUnit5 and uncomment JUnit4 dependencies here. Please also check "test" section
11+
// testImplementation group: 'junit', name: 'junit', version: '4.13.1'
12+
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-params', version: '5.8.1'
13+
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.8.1'
14+
15+
// used for testing code generation
16+
testImplementation group: 'junit', name: 'junit', version: junit4Version
17+
testImplementation group: 'org.junit.platform', name: 'junit-platform-console-standalone', version: junit4PlatformVersion
18+
testImplementation group: 'org.mockito', name: 'mockito-core', version: mockitoVersion
19+
testImplementation group: 'org.mockito', name: 'mockito-inline', version: mockitoInlineVersion
20+
testImplementation group: 'org.jacoco', name: 'org.jacoco.report', version: jacocoVersion
21+
22+
testImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa', version: springBootVersion
23+
}
24+
25+
configurations {
26+
all {
27+
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
28+
}
29+
}
30+
31+
test {
32+
if (System.getProperty('DEBUG', 'false') == 'true') {
33+
jvmArgs '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=9009'
34+
}
35+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package org.utbot.examples.spring.autowiring
2+
3+
import org.junit.jupiter.api.Test
4+
import org.springframework.data.jpa.repository.JpaRepository
5+
import org.springframework.data.repository.PagingAndSortingRepository
6+
import org.utbot.framework.plugin.api.CodegenLanguage
7+
import org.utbot.framework.plugin.api.MockStrategyApi
8+
import org.utbot.testcheckers.eq
9+
import org.utbot.testing.*
10+
import kotlin.reflect.full.functions
11+
import kotlin.reflect.KFunction1
12+
import kotlin.reflect.KFunction2
13+
14+
internal class OrderServiceTests : UtValueTestCaseChecker(
15+
testClass = OrderService::class,
16+
pipelines = listOf(TestLastStage(language = CodegenLanguage.JAVA))
17+
) {
18+
@Test
19+
fun testGetOrders() {
20+
checkMocks(
21+
method = OrderService::getOrders,
22+
branches = eq(1),
23+
{ mocks, r ->
24+
val orderRepository = mocks.singleMock("orderRepository", findAllRepositoryCall)
25+
orderRepository.value<List<Order>?>(0) == r
26+
},
27+
coverage = DoNotCalculate,
28+
mockStrategy = MockStrategyApi.OTHER_CLASSES,
29+
additionalDependencies = arrayOf(JpaRepository::class.java, PagingAndSortingRepository::class.java),
30+
)
31+
}
32+
33+
@Test
34+
fun testCreateOrder() {
35+
checkMocksWithExceptions(
36+
method = OrderService::createOrder,
37+
// TODO: replace with `branches = eq(1)` after fix of https://github.com/UnitTestBot/UTBotJava/issues/2367
38+
branches = ignoreExecutionsNumber,
39+
{ _: Order?, mocks, r: Result<Order?> ->
40+
val orderRepository = mocks.singleMock("orderRepository", saveRepositoryCall)
41+
orderRepository.value<Order?>(0) == r.getOrNull()
42+
},
43+
coverage = DoNotCalculate,
44+
mockStrategy = MockStrategyApi.OTHER_CLASSES,
45+
additionalDependencies = arrayOf(JpaRepository::class.java, PagingAndSortingRepository::class.java),
46+
)
47+
}
48+
49+
@Suppress("UNCHECKED_CAST")
50+
private val findAllRepositoryCall: KFunction1<OrderRepository, List<Order>?> =
51+
OrderRepository::class
52+
.functions
53+
.single { it.name == "findAll" && it.parameters.size == 1 }
54+
as KFunction1<OrderRepository, List<Order>?>
55+
56+
57+
@Suppress("UNCHECKED_CAST")
58+
private val saveRepositoryCall: KFunction2<OrderRepository, Order?, Order?> =
59+
OrderRepository::class
60+
.functions
61+
.single { it.name == "save" && it.parameters.size == 2 }
62+
as KFunction2<OrderRepository, Order?, Order?>
63+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Configuration>
3+
<Appenders>
4+
<File name="FrameworkAppender"
5+
append="false"
6+
fileName="logs/framework.log"
7+
filePattern="logs/framework-%d{MM-dd-yyyy}.log.gz"
8+
ignoreExceptions="false">
9+
10+
<PatternLayout pattern="%d{HH:mm:ss.SSS} | %-5level | %-25c{1} | %msg%n"/>
11+
</File>
12+
13+
<Console name="Console" target="SYSTEM_OUT">
14+
<ThresholdFilter level="DEBUG" onMatch="NEUTRAL" onMismatch="DENY"/>
15+
<PatternLayout pattern="%d{HH:mm:ss.SSS} | %-5level | %-25c{1} | %msg%n"/>
16+
</Console>
17+
</Appenders>
18+
<Loggers>
19+
<!-- Uncomment this logger to see path -->
20+
<Logger name="org.utbot.engine.UtBotSymbolicEngine.path" level="debug"/>
21+
22+
23+
<!-- Set this logger level to TRACE to see SMT requests, and SAT/UNSAT/UNKNOWN responses -->
24+
<Logger name="org.utbot.engine.pc" level="debug"/>
25+
26+
<!-- Not interested in summarization logs now -->
27+
<Logger name="org.utbot.summary" level="info"/>
28+
29+
<Logger name="soot.PackManager" level="INFO"/>
30+
31+
<Root level="debug">
32+
<AppenderRef ref="Console"/>
33+
<AppenderRef ref="FrameworkAppender"/>
34+
</Root>
35+
</Loggers>
36+
</Configuration>

utbot-testing/src/main/kotlin/org/utbot/testing/UtValueTestCaseChecker.kt

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,81 @@ abstract class UtValueTestCaseChecker(
530530
additionalMockAlwaysClasses = additionalMockAlwaysClasses
531531
)
532532

533+
protected inline fun <reified R> checkMocksWithExceptions(
534+
method: KFunction1<*, R>,
535+
branches: ExecutionsNumberMatcher,
536+
vararg matchers: (Mocks, Result<R>) -> Boolean,
537+
coverage: CoverageMatcher = Full,
538+
mockStrategy: MockStrategyApi = NO_MOCKS,
539+
additionalDependencies: Array<Class<*>> = emptyArray(),
540+
additionalMockAlwaysClasses: Set<ClassId> = emptySet()
541+
) = internalCheck(
542+
method, mockStrategy, branches, matchers, coverage,
543+
arguments = ::withMocksAndExceptions,
544+
additionalDependencies = additionalDependencies,
545+
additionalMockAlwaysClasses = additionalMockAlwaysClasses
546+
)
547+
548+
protected inline fun <reified T, reified R> checkMocksWithExceptions(
549+
method: KFunction2<*, T, R>,
550+
branches: ExecutionsNumberMatcher,
551+
vararg matchers: (T, Mocks, Result<R>) -> Boolean,
552+
coverage: CoverageMatcher = Full,
553+
mockStrategy: MockStrategyApi = NO_MOCKS,
554+
additionalDependencies: Array<Class<*>> = emptyArray(),
555+
additionalMockAlwaysClasses: Set<ClassId> = emptySet()
556+
) = internalCheck(
557+
method, mockStrategy, branches, matchers, coverage, T::class,
558+
arguments = ::withMocksAndExceptions,
559+
additionalDependencies = additionalDependencies,
560+
additionalMockAlwaysClasses = additionalMockAlwaysClasses
561+
)
562+
563+
protected inline fun <reified T1, reified T2, reified R> checkMocksWithExceptions(
564+
method: KFunction3<*, T1, T2, R>,
565+
branches: ExecutionsNumberMatcher,
566+
vararg matchers: (T1, T2, Mocks, Result<R>) -> Boolean,
567+
coverage: CoverageMatcher = Full,
568+
mockStrategy: MockStrategyApi = NO_MOCKS,
569+
additionalDependencies: Array<Class<*>> = emptyArray(),
570+
additionalMockAlwaysClasses: Set<ClassId> = emptySet()
571+
) = internalCheck(
572+
method, mockStrategy, branches, matchers, coverage, T1::class, T2::class,
573+
arguments = ::withMocksAndExceptions,
574+
additionalDependencies = additionalDependencies,
575+
additionalMockAlwaysClasses = additionalMockAlwaysClasses
576+
)
577+
578+
protected inline fun <reified T1, reified T2, reified T3, reified R> checkMocksWithExceptions(
579+
method: KFunction4<*, T1, T2, T3, R>,
580+
branches: ExecutionsNumberMatcher,
581+
vararg matchers: (T1, T2, T3, Mocks, Result<R>) -> Boolean,
582+
coverage: CoverageMatcher = Full,
583+
mockStrategy: MockStrategyApi = NO_MOCKS,
584+
additionalDependencies: Array<Class<*>> = emptyArray(),
585+
additionalMockAlwaysClasses: Set<ClassId> = emptySet()
586+
) = internalCheck(
587+
method, mockStrategy, branches, matchers, coverage, T1::class, T2::class, T3::class,
588+
arguments = ::withMocksAndExceptions,
589+
additionalDependencies = additionalDependencies,
590+
additionalMockAlwaysClasses = additionalMockAlwaysClasses
591+
)
592+
593+
protected inline fun <reified T1, reified T2, reified T3, reified T4, reified R> checkMocksWithExceptions(
594+
method: KFunction5<*, T1, T2, T3, T4, R>,
595+
branches: ExecutionsNumberMatcher,
596+
vararg matchers: (T1, T2, T3, T4, Mocks, Result<R>) -> Boolean,
597+
coverage: CoverageMatcher = Full,
598+
mockStrategy: MockStrategyApi = NO_MOCKS,
599+
additionalDependencies: Array<Class<*>> = emptyArray(),
600+
additionalMockAlwaysClasses: Set<ClassId> = emptySet()
601+
) = internalCheck(
602+
method, mockStrategy, branches, matchers, coverage, T1::class, T2::class, T3::class, T4::class,
603+
arguments = ::withMocksAndExceptions,
604+
additionalDependencies = additionalDependencies,
605+
additionalMockAlwaysClasses = additionalMockAlwaysClasses
606+
)
607+
533608
// check paramsBefore, mocks and instrumentation and result value
534609
protected inline fun <reified R> checkMocksAndInstrumentation(
535610
method: KFunction1<*, R>,
@@ -2232,6 +2307,9 @@ fun withMocks(ex: UtValueExecution<*>) = ex.paramsBefore + listOf(ex.mocks) + ex
22322307
fun withMocksAndInstrumentation(ex: UtValueExecution<*>) =
22332308
ex.paramsBefore + listOf(ex.mocks) + listOf(ex.instrumentation) + ex.evaluatedResult
22342309

2310+
fun withMocksAndExceptions(ex: UtValueExecution<*>) =
2311+
ex.paramsBefore + listOf(ex.mocks) + ex.returnValue
2312+
22352313
fun withMocksInstrumentationAndThis(ex: UtValueExecution<*>) =
22362314
listOf(ex.callerBefore) + ex.paramsBefore + listOf(ex.mocks) + listOf(ex.instrumentation) + ex.evaluatedResult
22372315

0 commit comments

Comments
 (0)