Skip to content

Commit 4833af7

Browse files
authored
Add autotests for Spring non-injected fields (#2426)
1 parent 1e571a9 commit 4833af7

File tree

17 files changed

+219
-65
lines changed

17 files changed

+219
-65
lines changed

utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgAbstractSpringTestClassConstructor.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import org.utbot.framework.plugin.api.UtSpringContextModel
2121
import org.utbot.framework.plugin.api.util.SpringModelUtils.getBeanNameOrNull
2222
import org.utbot.framework.plugin.api.util.id
2323
import java.lang.Exception
24+
import java.util.Collections.max
2425

2526
abstract class CgAbstractSpringTestClassConstructor(context: CgContext) :
2627
CgAbstractTestClassConstructor<SpringTestClassModel>(context) {
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.utbot.examples.spring.autowiring;
22

33
import org.springframework.data.jpa.repository.JpaRepository;
4+
import org.utbot.examples.spring.autowiring.oneBeanForOneType.Order;
45

56
public interface OrderRepository extends JpaRepository<Order, Long> {
67
}

utbot-spring-sample/src/main/java/org/utbot/examples/spring/autowiring/Order.java renamed to utbot-spring-sample/src/main/java/org/utbot/examples/spring/autowiring/oneBeanForOneType/Order.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package org.utbot.examples.spring.autowiring;
1+
package org.utbot.examples.spring.autowiring.oneBeanForOneType;
22

33
import lombok.*;
44
import lombok.extern.jackson.Jacksonized;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package org.utbot.examples.spring.autowiring.oneBeanForOneType;
2+
3+
import org.springframework.beans.factory.annotation.Autowired;
4+
import org.springframework.stereotype.Service;
5+
import org.utbot.examples.spring.autowiring.OrderRepository;
6+
7+
import java.util.ArrayList;
8+
import java.util.List;
9+
10+
@Service
11+
public class ServiceWithInjectedAndNonInjectedField {
12+
13+
public List<Order> selectedOrders = new ArrayList<>();
14+
15+
@Autowired
16+
private OrderRepository orderRepository;
17+
18+
public Integer getOrdersSize() {
19+
return orderRepository.findAll().size() + selectedOrders.size();
20+
}
21+
22+
}

utbot-spring-sample/src/main/java/org/utbot/examples/spring/autowiring/OrderService.java renamed to utbot-spring-sample/src/main/java/org/utbot/examples/spring/autowiring/oneBeanForOneType/ServiceWithInjectedField.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
package org.utbot.examples.spring.autowiring;
1+
package org.utbot.examples.spring.autowiring.oneBeanForOneType;
22

33
import org.springframework.beans.factory.annotation.Autowired;
44
import org.springframework.stereotype.Service;
5+
import org.utbot.examples.spring.autowiring.OrderRepository;
56

67
import java.util.List;
78

89
@Service
9-
public class OrderService {
10+
public class ServiceWithInjectedField {
1011

1112
@Autowired
1213
private OrderRepository orderRepository;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package org.utbot.examples.spring.autowiring.twoAndMoreBeansForOneType;
2+
3+
public class Person {
4+
private String firstName;
5+
private String lastName;
6+
7+
private Integer age;
8+
9+
public Person(String firstName, String secondName, Integer age) {
10+
this.firstName = firstName;
11+
this.lastName = secondName;
12+
this.age = age;
13+
}
14+
15+
public Integer getAge(){
16+
return age;
17+
}
18+
19+
public String name() {
20+
return firstName + " " + lastName;
21+
}
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package org.utbot.examples.spring.autowiring.twoAndMoreBeansForOneType;
2+
3+
import org.springframework.context.annotation.Bean;
4+
import org.springframework.context.annotation.Configuration;
5+
6+
@Configuration
7+
public class PersonConfig {
8+
@Bean
9+
public Person personOne() {
10+
return new Person("Eg", "or", 7);
11+
}
12+
13+
@Bean
14+
public Person personTwo() {
15+
return new Person("Kir", "ill", 6);
16+
}
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package org.utbot.examples.spring.autowiring.twoAndMoreBeansForOneType;
2+
3+
import org.springframework.beans.factory.annotation.Autowired;
4+
import org.springframework.stereotype.Service;
5+
6+
@Service
7+
public class PersonService {
8+
@Autowired
9+
private Person personOne;
10+
11+
@Autowired
12+
private Person personTwo;
13+
14+
public Integer ageSum(){
15+
return personOne.getAge() + personTwo.getAge();
16+
}
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package org.utbot.examples.spring.autowiring.oneBeanForOneType
2+
3+
import org.junit.jupiter.api.Test
4+
import org.utbot.examples.spring.utils.findAllRepositoryCall
5+
import org.utbot.examples.spring.utils.springAdditionalDependencies
6+
import org.utbot.examples.spring.utils.springMockStrategy
7+
import org.utbot.examples.spring.utils.standardSpringTestingConfigurations
8+
import org.utbot.framework.plugin.api.MockStrategyApi
9+
import org.utbot.testcheckers.eq
10+
import org.utbot.testing.DoNotCalculate
11+
import org.utbot.testing.UtValueTestCaseChecker
12+
import org.utbot.testing.ignoreExecutionsNumber
13+
import org.utbot.testing.isException
14+
import org.utbot.testing.singleMock
15+
import org.utbot.testing.value
16+
17+
internal class ServiceWithInjectedAndNonInjectedFieldTests: UtValueTestCaseChecker(
18+
testClass = ServiceWithInjectedAndNonInjectedField::class,
19+
configurations = standardSpringTestingConfigurations
20+
) {
21+
@Test
22+
fun testGetOrdersSize() {
23+
checkThisMocksAndExceptions(
24+
method = ServiceWithInjectedAndNonInjectedField::getOrdersSize,
25+
// TODO: replace with `branches = eq(3)`
26+
// after the fix of `speculativelyCannotProduceNullPointerException` in SpringApplicationContext
27+
branches = ignoreExecutionsNumber,
28+
{ thisInstance, mocks, r: Result<Int> ->
29+
val orderRepository = mocks.singleMock("orderRepository", findAllRepositoryCall)
30+
val repositorySize = orderRepository.value<List<Order>?>()!!.size
31+
repositorySize + thisInstance.selectedOrders.size == r.getOrNull()
32+
},
33+
{ _, _, r: Result<Int> -> r.isException<NullPointerException>() },
34+
coverage = DoNotCalculate,
35+
mockStrategy = springMockStrategy,
36+
additionalDependencies = springAdditionalDependencies,
37+
)
38+
}
39+
}
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,47 @@
1-
package org.utbot.examples.spring.autowiring
1+
package org.utbot.examples.spring.autowiring.oneBeanForOneType
22

33
import org.junit.jupiter.api.Test
4+
import org.utbot.examples.spring.utils.findAllRepositoryCall
5+
import org.utbot.examples.spring.utils.saveRepositoryCall
46
import org.utbot.examples.spring.utils.springAdditionalDependencies
7+
import org.utbot.examples.spring.utils.springMockStrategy
58
import org.utbot.examples.spring.utils.standardSpringTestingConfigurations
69
import org.utbot.framework.plugin.api.MockStrategyApi
710
import org.utbot.testcheckers.eq
811
import org.utbot.testing.*
9-
import kotlin.reflect.full.functions
10-
import kotlin.reflect.KFunction1
11-
import kotlin.reflect.KFunction2
1212

13-
internal class OrderServiceTests : UtValueTestCaseChecker(
14-
testClass = OrderService::class,
13+
internal class ServiceWithInjectedFieldTests : UtValueTestCaseChecker(
14+
testClass = ServiceWithInjectedField::class,
1515
configurations = standardSpringTestingConfigurations
1616
) {
1717
@Test
1818
fun testGetOrders() {
1919
checkMocks(
20-
method = OrderService::getOrders,
20+
method = ServiceWithInjectedField::getOrders,
2121
branches = eq(1),
2222
{ mocks, r ->
2323
val orderRepository = mocks.singleMock("orderRepository", findAllRepositoryCall)
2424
orderRepository.value<List<Order>?>() == r
2525
},
2626
coverage = DoNotCalculate,
27-
mockStrategy = MockStrategyApi.OTHER_CLASSES,
27+
mockStrategy = springMockStrategy,
2828
additionalDependencies = springAdditionalDependencies,
2929
)
3030
}
3131

3232
@Test
3333
fun testCreateOrder() {
34-
checkMocksWithExceptions(
35-
method = OrderService::createOrder,
34+
checkThisMocksAndExceptions(
35+
method = ServiceWithInjectedField::createOrder,
3636
// TODO: replace with `branches = eq(1)` after fix of https://github.com/UnitTestBot/UTBotJava/issues/2367
3737
branches = ignoreExecutionsNumber,
38-
{ _: Order?, mocks, r: Result<Order?> ->
38+
{ _, _, mocks, r: Result<Order?> ->
3939
val orderRepository = mocks.singleMock("orderRepository", saveRepositoryCall)
4040
orderRepository.value<Order?>() == r.getOrNull()
4141
},
4242
coverage = DoNotCalculate,
43-
mockStrategy = MockStrategyApi.OTHER_CLASSES,
43+
mockStrategy = springMockStrategy,
4444
additionalDependencies = springAdditionalDependencies,
4545
)
4646
}
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?>
6247
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package org.utbot.examples.spring.utils
2+
3+
import org.utbot.examples.spring.autowiring.OrderRepository
4+
import org.utbot.examples.spring.autowiring.oneBeanForOneType.Order
5+
import kotlin.reflect.KFunction1
6+
import kotlin.reflect.KFunction2
7+
import kotlin.reflect.full.functions
8+
9+
@Suppress("UNCHECKED_CAST")
10+
val findAllRepositoryCall: KFunction1<OrderRepository, List<Order>?> =
11+
OrderRepository::class
12+
.functions
13+
.single { it.name == "findAll" && it.parameters.size == 1 }
14+
as KFunction1<OrderRepository, List<Order>?>
15+
16+
17+
@Suppress("UNCHECKED_CAST")
18+
val saveRepositoryCall: KFunction2<OrderRepository, Order?, Order?> =
19+
OrderRepository::class
20+
.functions
21+
.single { it.name == "save" && it.parameters.size == 2 }
22+
as KFunction2<OrderRepository, Order?, Order?>

utbot-spring-test/src/test/kotlin/org/utbot/examples/spring/utils/SpringTestingConfiguration.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,19 @@ import org.springframework.data.jpa.repository.JpaRepository
44
import org.springframework.data.repository.PagingAndSortingRepository
55
import org.utbot.framework.codegen.domain.ParametrizedTestSource
66
import org.utbot.framework.plugin.api.CodegenLanguage
7+
import org.utbot.framework.plugin.api.MockStrategyApi
8+
import org.utbot.framework.plugin.api.SpringApplicationContext
9+
import org.utbot.framework.plugin.api.SpringSettings
10+
import org.utbot.framework.plugin.api.SpringTestType
711
import org.utbot.testing.SpringConfiguration
812
import org.utbot.testing.TestExecution
913

1014
val standardSpringTestingConfigurations: List<SpringConfiguration> = listOf(
1115
SpringConfiguration(CodegenLanguage.JAVA, ParametrizedTestSource.DO_NOT_PARAMETRIZE, TestExecution)
1216
)
1317

18+
val springMockStrategy = MockStrategyApi.OTHER_CLASSES
19+
1420
val springAdditionalDependencies: Array<Class<*>> = arrayOf(
1521
JpaRepository::class.java,
1622
PagingAndSortingRepository::class.java,

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

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ package org.utbot.testing
33
import org.utbot.framework.codegen.domain.ParametrizedTestSource
44
import org.utbot.framework.codegen.domain.ProjectType
55
import org.utbot.framework.plugin.api.CodegenLanguage
6+
import org.utbot.framework.plugin.api.SpringApplicationContext
7+
import org.utbot.framework.plugin.api.SpringSettings
8+
import org.utbot.framework.plugin.api.SpringTestType
69

710
abstract class AbstractConfiguration(
811
val projectType: ProjectType,
@@ -21,4 +24,12 @@ data class SpringConfiguration(
2124
override val language: CodegenLanguage,
2225
override val parametrizedTestSource: ParametrizedTestSource,
2326
override val lastStage: Stage,
24-
): AbstractConfiguration(ProjectType.Spring, language, parametrizedTestSource, lastStage)
27+
): AbstractConfiguration(ProjectType.Spring, language, parametrizedTestSource, lastStage)
28+
29+
val defaultSpringApplicationContext = SpringApplicationContext(
30+
mockInstalled = true,
31+
staticsMockingIsConfigured = true,
32+
shouldUseImplementors = false,
33+
springTestType = SpringTestType.UNIT_TEST,
34+
springSettings = SpringSettings.AbsentSpringSettings(),
35+
)

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

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -268,13 +268,7 @@ class TestCodeGeneratorPipeline(private val testInfrastructureConfiguration: Tes
268268
parameterizedTestSource = parametrizedTestSource,
269269
runtimeExceptionTestsBehaviour = runtimeExceptionTestsBehaviour,
270270
enableTestsTimeout = enableTestsTimeout,
271-
springCodeGenerationContext = SpringApplicationContext(
272-
mockInstalled = true,
273-
staticsMockingIsConfigured = true,
274-
shouldUseImplementors = false,
275-
springTestType = SpringTestType.UNIT_TEST,
276-
springSettings = SpringSettings.AbsentSpringSettings(),
277-
)
271+
springCodeGenerationContext = defaultSpringApplicationContext,
278272
)
279273
ProjectType.PureJvm -> CodeGenerator(
280274
classUnderTest.id,

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@ import org.utbot.engine.UtBotSymbolicEngine
99
import org.utbot.engine.util.mockListeners.ForceMockListener
1010
import org.utbot.engine.util.mockListeners.ForceStaticMockListener
1111
import org.utbot.framework.UtSettings
12+
import org.utbot.framework.plugin.api.ApplicationContext
1213
import org.utbot.framework.plugin.api.ClassId
1314
import org.utbot.framework.plugin.api.ExecutableId
1415
import org.utbot.framework.plugin.api.MockStrategyApi
16+
import org.utbot.framework.plugin.api.SpringApplicationContext
1517
import org.utbot.framework.plugin.api.TestCaseGenerator
1618
import org.utbot.framework.plugin.api.UtError
1719
import org.utbot.framework.plugin.api.UtExecution
@@ -35,14 +37,16 @@ class TestSpecificTestCaseGenerator(
3537
engineActions: MutableList<(UtBotSymbolicEngine) -> Unit> = mutableListOf(),
3638
isCanceled: () -> Boolean = { false },
3739
private val taintConfigurationProvider: TaintConfigurationProvider? = null,
40+
applicationContext: ApplicationContext = ApplicationContext(),
3841
): TestCaseGenerator(
3942
listOf(buildDir),
4043
classpath,
4144
dependencyPaths,
4245
JdkInfoDefaultProvider().info,
4346
engineActions,
4447
isCanceled,
45-
forceSootReload = false
48+
forceSootReload = false,
49+
applicationContext = applicationContext,
4650
) {
4751

4852
private val logger = KotlinLogging.logger {}

0 commit comments

Comments
 (0)