Skip to content

Commit 199a315

Browse files
First autotests for tests generation on Spring projects (#2365)
1 parent 8cfd494 commit 199a315

File tree

13 files changed

+309
-7
lines changed

13 files changed

+309
-7
lines changed

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: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ dependencies {
4646
implementation group: 'com.github.UnitTestBot.ksmt', name: 'ksmt-z3', version: ksmtVersion
4747
}
4848

49+
// This is required to avoid conflict between SpringBoot standard logger and the logger of our project.
50+
// See https://stackoverflow.com/a/28735604 for more details.
4951
test {
5052
if (System.getProperty('DEBUG', 'false') == 'true') {
5153
jvmArgs '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=9009'

utbot-spring-sample/build.gradle

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
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+
// This is required to avoid conflict between SpringBoot standard logger and the logger of our project.
16+
// See https://stackoverflow.com/a/28735604 for more details.
17+
configurations {
18+
all {
19+
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
20+
}
21+
}
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: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
dependencies {
2+
testImplementation(project(":utbot-framework"))
3+
testImplementation project(':utbot-testing')
4+
testImplementation project(':utbot-spring-sample')
5+
6+
// To use JUnit4, comment out JUnit5 and uncomment JUnit4 dependencies here. Please also check "test" section
7+
// testImplementation group: 'junit', name: 'junit', version: '4.13.1'
8+
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-params', version: '5.8.1'
9+
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.8.1'
10+
11+
// used for testing code generation
12+
testImplementation group: 'junit', name: 'junit', version: junit4Version
13+
testImplementation group: 'org.junit.platform', name: 'junit-platform-console-standalone', version: junit4PlatformVersion
14+
testImplementation group: 'org.mockito', name: 'mockito-core', version: mockitoVersion
15+
testImplementation group: 'org.mockito', name: 'mockito-inline', version: mockitoInlineVersion
16+
testImplementation group: 'org.jacoco', name: 'org.jacoco.report', version: jacocoVersion
17+
18+
testImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa', version: springBootVersion
19+
}
20+
21+
configurations {
22+
all {
23+
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
24+
}
25+
}
26+
27+
test {
28+
if (System.getProperty('DEBUG', 'false') == 'true') {
29+
jvmArgs '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=9009'
30+
}
31+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package org.utbot.examples.spring.autowiring
2+
3+
import org.junit.jupiter.api.Test
4+
import org.utbot.examples.spring.utils.springAdditionalDependencies
5+
import org.utbot.examples.spring.utils.standardSpringTestingConfigurations
6+
import org.utbot.framework.plugin.api.MockStrategyApi
7+
import org.utbot.testcheckers.eq
8+
import org.utbot.testing.*
9+
import kotlin.reflect.full.functions
10+
import kotlin.reflect.KFunction1
11+
import kotlin.reflect.KFunction2
12+
13+
internal class OrderServiceTests : UtValueTestCaseChecker(
14+
testClass = OrderService::class,
15+
configurations = standardSpringTestingConfigurations
16+
) {
17+
@Test
18+
fun testGetOrders() {
19+
checkMocks(
20+
method = OrderService::getOrders,
21+
branches = eq(1),
22+
{ mocks, r ->
23+
val orderRepository = mocks.singleMock("orderRepository", findAllRepositoryCall)
24+
orderRepository.value<List<Order>?>() == r
25+
},
26+
coverage = DoNotCalculate,
27+
mockStrategy = MockStrategyApi.OTHER_CLASSES,
28+
additionalDependencies = springAdditionalDependencies,
29+
)
30+
}
31+
32+
@Test
33+
fun testCreateOrder() {
34+
checkMocksWithExceptions(
35+
method = OrderService::createOrder,
36+
// TODO: replace with `branches = eq(1)` after fix of https://github.com/UnitTestBot/UTBotJava/issues/2367
37+
branches = ignoreExecutionsNumber,
38+
{ _: Order?, mocks, r: Result<Order?> ->
39+
val orderRepository = mocks.singleMock("orderRepository", saveRepositoryCall)
40+
orderRepository.value<Order?>() == r.getOrNull()
41+
},
42+
coverage = DoNotCalculate,
43+
mockStrategy = MockStrategyApi.OTHER_CLASSES,
44+
additionalDependencies = springAdditionalDependencies,
45+
)
46+
}
47+
48+
@Suppress("UNCHECKED_CAST")
49+
private val findAllRepositoryCall: KFunction1<OrderRepository, List<Order>?> =
50+
OrderRepository::class
51+
.functions
52+
.single { it.name == "findAll" && it.parameters.size == 1 }
53+
as KFunction1<OrderRepository, List<Order>?>
54+
55+
56+
@Suppress("UNCHECKED_CAST")
57+
private val saveRepositoryCall: KFunction2<OrderRepository, Order?, Order?> =
58+
OrderRepository::class
59+
.functions
60+
.single { it.name == "save" && it.parameters.size == 2 }
61+
as KFunction2<OrderRepository, Order?, Order?>
62+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package org.utbot.examples.spring.utils
2+
3+
import org.springframework.data.jpa.repository.JpaRepository
4+
import org.springframework.data.repository.PagingAndSortingRepository
5+
import org.utbot.framework.codegen.domain.ParametrizedTestSource
6+
import org.utbot.framework.plugin.api.CodegenLanguage
7+
import org.utbot.testing.SpringConfiguration
8+
import org.utbot.testing.TestExecution
9+
10+
val standardSpringTestingConfigurations: List<SpringConfiguration> = listOf(
11+
SpringConfiguration(CodegenLanguage.JAVA, ParametrizedTestSource.DO_NOT_PARAMETRIZE, TestExecution)
12+
)
13+
14+
val springAdditionalDependencies: Array<Class<*>> = arrayOf(
15+
JpaRepository::class.java,
16+
PagingAndSortingRepository::class.java,
17+
)
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>

0 commit comments

Comments
 (0)