Reputation: 61
how can i test a method with the @Transaction annotation. I wrote a method which works if i test it when the application is running (manually). But my test for this doesn't work. My goal is to write a test which make sure that my transaction method works when a exception happened, so nothing is stored in the DB. Maybe it is enough to test that the Transaction annotation exist, in the belief that spring works fine. :/ But that is ugly for me.
So my goal is not to test the functionality of springs transaction. My goal is to have a test which make sure that nothing will be stored in the db if a exception happen. Maybe there is a better way to test it.
I drop every time the database before the test is running. The id of the company is every time a another random long.
spring:
data:
mongodb:
uri: mongodb://okAdmin:test@mongo_one:27017,mongo_two:27018,mongo_three:27019/?replicaSet=rs0
database: "ok"
auto-index-creation: false
@Configuration
public class MongoTransactionConfig extends AbstractMongoClientConfiguration {
@Value("${spring.data.mongodb.database}")
private String database;
@Value("${spring.data.mongodb.uri}")
private String mongo_uri;
@Bean
MongoTransactionManager transactionManager(MongoDatabaseFactory mongoDatabaseFactory) {
return new MongoTransactionManager(mongoDatabaseFactory);
}
@Bean
public MongoClient mongoClient() {
return MongoClients.create(mongo_uri);
}
@Override
protected String getDatabaseName() {
return database;
}
}
@Slf4j
@Service
public class CompanyService {
public static final int MIN_NUMBER_OF_BRANCHES = 1;
private final CompanyRepository companyRepository;
@Autowired
public CompanyService(@NonNull CompanyRepository companyRepository) {
this.companyRepository = companyRepository;
}
// TODO : TEST
@Transactional // (rollbackFor = {StoreException.class}) => NOT WORKING FOR TESTS/NO CATCHING
public void addBranch(@NonNull Branch branch){
log.debug("Service: Add branch to company");
long companyId = branch.getCompanyId();
companyRepository.addBranch(branch);
long branches_number = companyRepository.countBranchesForCompany(companyId);
if (branches_number == MIN_NUMBER_OF_BRANCHES) {
companyRepository.setSignupCompleted(companyId, true);
}
}
}
@SpringBootTest(properties = {
"spring.data.mongodb.database=ok_test"
})
//@Transactional
class CompanyServiceMongoTest {
private final String COLLECTION_BRANCHES = "branches";
@Autowired
private MongoTemplate mongoTemplate;
@Autowired
private CompanyService testObject;
@Autowired
private CompanyRepository companyRepository;
@Test
void addBranch_test_transaction_company_not_saved(){
// PREPARE
Branch branchTestDummy = BranchTest.createBranchTestDummy();
Query branchQuery = new Query();
branchQuery.addCriteria(Criteria.where("company_id").is(branchTestDummy.getCompanyId()));
// ACTION
assertThrows(StoreException.class, ()-> testObject.addBranch(branchTestDummy));
// CHECK
boolean exists = mongoTemplate.exists(branchQuery, BranchDao.class, COLLECTION_BRANCHES);
assertFalse(exists);
}
}
org.opentest4j.AssertionFailedError:
Expected :false
Actual :true
at org.junit.jupiter.api.AssertionUtils.fail(AssertionUtils.java:55)
at org.junit.jupiter.api.AssertFalse.assertFalse(AssertFalse.java:40)
at org.junit.jupiter.api.AssertFalse.assertFalse(AssertFalse.java:35)
at org.junit.jupiter.api.Assertions.assertFalse(Assertions.java:210)
at com.localkoop.server.components.company.core.services.CompanyServiceMongoTest.addBranch_test_transaction_company_not_saved(CompanyServiceMongoTest.java:102)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:567)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:686)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:212)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:208)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:137)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:71)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:135)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1507)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1507)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:248)
at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$5(DefaultLauncher.java:211)
at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:226)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:199)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:132)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:69)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)
2020-06-17 11:12:34.635 INFO 182967 --- [mongo_two:27017] org.mongodb.driver.connection : Opened connection [connectionId{localValue:1426609, serverValue:1511263}] to mongo_two:27017
2020-06-17 11:12:34.635 DEBUG 182967 --- [mongo_two:27017] org.mongodb.driver.cluster : Checking status of mongo_two:27017
2020-06-17 11:12:34.635 DEBUG 182967 --- [mongo_two:27017] org.mongodb.driver.protocol.command : Sending command '{"ismaster": 1, "$db": "admin", "$clusterTime": {"clusterTime": {"$timestamp": {"t": 1592385154, "i": 1}}, "signature": {"hash": {"$binary": {"base64": "2Qn1NUq/OPeFI3jd2aPIoloM/x0=", "subType": "00"}}, "keyId": 6837089852169650179}}}' with request id 2853624 to database admin on connection [connectionId{localValue:1426609, serverValue:1511263}] to server mongo_two:27017
2020-06-17 11:12:34.635 DEBUG 182967 --- [mongo_two:27017] org.mongodb.driver.protocol.command : Execution of command with request id 2853624 completed successfully in 0.32 ms on connection [connectionId{localValue:1426609, serverValue:1511263}] to server mongo_two:27017
2020-06-17 11:12:34.636 INFO 182967 --- [mongo_two:27017] org.mongodb.driver.cluster : Monitor thread successfully connected to server with description ServerDescription{address=mongo_two:27017, type=REPLICA_SET_PRIMARY, state=CONNECTED, ok=true, minWireVersion=0, maxWireVersion=8, maxDocumentSize=16777216, logicalSessionTimeoutMinutes=30, roundTripTimeNanos=403948, setName='rs0', canonicalAddress=mongo_one:27017, hosts=[mongo_one:27017], passives=[mongo_two:27017, mongo_three:27017], arbiters=[], primary='mongo_one:27017', tagSet=TagSet{[]}, electionId=7fffffff0000000000000009, setVersion=1, lastWriteDate=Wed Jun 17 11:12:34 CEST 2020, lastUpdateTimeNanos=9570708142930}
2020-06-17 11:12:34.636 INFO 182967 --- [mongo_two:27017] org.mongodb.driver.cluster : Adding discovered server mongo_three:27017 to client view of cluster
2020-06-17 11:12:34.636 INFO 182967 --- [mongo_two:27017] org.mongodb.driver.cluster : Canonical address mongo_one:27017 does not match server address. Removing mongo_two:27017 from client view of cluster
2020-06-17 11:12:34.636 DEBUG 182967 --- [mongo_two:27017] org.mongodb.driver.cluster : Updating cluster description to {type=REPLICA_SET, servers=[{address=mongo_one:27017, type=REPLICA_SET_PRIMARY, roundTripTime=0.6 ms, state=CONNECTED}, {address=mongo_three:27017, type=UNKNOWN, state=CONNECTING}]
2020-06-17 11:12:34.636 DEBUG 182967 --- [mongo_two:27017] org.mongodb.driver.connection : Closing connection connectionId{localValue:1426609, serverValue:1511263}
2020-06-17 11:12:34.637 INFO 182967 --- [ngo_three:27017] org.mongodb.driver.connection : Opened connection [connectionId{localValue:1426610, serverValue:1511264}] to mongo_three:27017
2020-06-17 11:12:34.637 DEBUG 182967 --- [ngo_three:27017] org.mongodb.driver.cluster : Checking status of mongo_three:27017
2020-06-17 11:12:34.637 DEBUG 182967 --- [ngo_three:27017] org.mongodb.driver.protocol.command : Sending command '{"ismaster": 1, "$db": "admin", "$clusterTime": {"clusterTime": {"$timestamp": {"t": 1592385154, "i": 1}}, "signature": {"hash": {"$binary": {"base64": "2Qn1NUq/OPeFI3jd2aPIoloM/x0=", "subType": "00"}}, "keyId": 6837089852169650179}}}' with request id 2853626 to database admin on connection [connectionId{localValue:1426610, serverValue:1511264}] to server mongo_three:27017
2020-06-17 11:12:34.637 DEBUG 182967 --- [ngo_three:27017] org.mongodb.driver.protocol.command : Execution of command with request id 2853626 completed successfully in 0.36 ms on connection [connectionId{localValue:1426610, serverValue:1511264}] to server mongo_three:27017
2020-06-17 11:12:34.637 INFO 182967 --- [ngo_three:27017] org.mongodb.driver.cluster : Monitor thread successfully connected to server with description ServerDescription{address=mongo_three:27017, type=REPLICA_SET_PRIMARY, state=CONNECTED, ok=true, minWireVersion=0, maxWireVersion=8, maxDocumentSize=16777216, logicalSessionTimeoutMinutes=30, roundTripTimeNanos=457039, setName='rs0', canonicalAddress=mongo_one:27017, hosts=[mongo_one:27017], passives=[mongo_two:27017, mongo_three:27017], arbiters=[], primary='mongo_one:27017', tagSet=TagSet{[]}, electionId=7fffffff0000000000000009, setVersion=1, lastWriteDate=Wed Jun 17 11:12:34 CEST 2020, lastUpdateTimeNanos=9570709659086}
2020-06-17 11:12:34.637 INFO 182967 --- [ngo_three:27017] org.mongodb.driver.cluster : Adding discovered server mongo_two:27017 to client view of cluster
2020-06-17 11:12:34.637 INFO 182967 --- [ngo_three:27017] org.mongodb.driver.cluster : Canonical address mongo_one:27017 does not match server address. Removing mongo_three:27017 from client view of cluster
2020-06-17 11:12:34.637 DEBUG 182967 --- [ngo_three:27017] org.mongodb.driver.cluster : Updating cluster description to {type=REPLICA_SET, servers=[{address=mongo_one:27017, type=REPLICA_SET_PRIMARY, roundTripTime=0.6 ms, state=CONNECTED}, {address=mongo_two:27017, type=UNKNOWN, state=CONNECTING}]
2020-06-17 11:12:34.637 DEBUG 182967 --- [ngo_three:27017] org.mongodb.driver.connection : Closing connection connectionId{localValue:1426610, serverValue:1511264}
THANK YOU FOR YOUR HELP
Upvotes: 6
Views: 8226
Reputation: 61
So i found a solution which works for me. I annotated my test class with
@DataMongoTest(excludeAutoConfiguration = EmbeddedMongoAutoConfiguration.class, includeFilters = @ComponentScan.Filter(Component.class))
@ActiveProfiles("test")
class CompanyServiceMongoTest {}
I don't know why the annotation @SpringBootTest doesn't work. I thought that @SpringBootTest is a "super context" of @DataMongoTest, but my tests doesn't work with @SpringBootTest annotation. Be aware to use @Transactional as annotation in the test class layer. It doesn't work fine with the transaction mechanism in the service.
Upvotes: 0
Reputation: 3659
Personally I would not write a unit test to test that @Transactional
works correctly. My reason is, the environment for the unit test execution is not the same as the environment the bean works in. I have seen too many cases where the unit tests work fine, but the actual system does not.
You can rather try to write an integration tests that will run against an instance of the system (send a request, trigger the functionality, look into the DB to see whether it is what you expect to see). Makes more sense to me, but may also be more time consuming to do.
Upvotes: 3