Testing a service that makes database calls, without a database
up vote
1
down vote
favorite
I'm working on a new service, for the past year I haven't needed to write tests from scratch. I've either been bug fixing, or adding features that require modification of tests, but not writing everything from scratch.
I need to make sure I'm doing things right. The unit tests below test a service that queries a database for data.
The *Proc files use Springs @Repository
annotation, and each one calls a different stored procedure in the database. For these tests I'm mocking everything. Have I done it correctly? Is there anything I have overlooked? Anything I've possibly missed? The tests all pass when I run them in my IDE or with maven. In this particular instance those method calls simply return the object(s) retrieved from the database, so there isn't any actual business logic in there apart from calling the get()
method from the proc objects that I'm mocking.
Have I done things the correct way?
@RunWith(MockitoJUnitRunner.class)
@SpringBootTest
public class FusServiceImplTest {
@Mock
private GetFileInfoByIdProc getFileInfobyIdProc;
@Mock
private GetFileInfoProc getFileInfoProc;
@Mock
private GetFileInfoByFileNameProc getFileInfoByFileNameProc;
@Mock
FileInfoVO voMock;
@Mock
FileInfoVO voMock2;
@InjectMocks
private FusServiceImpl service;
@Test
public void whenGetFileById_thenReturnFile(){
final Long ID = 99999L;
when(getFileInfobyIdProc.get(ID)).thenReturn(voMock);
FileInfoVO voResult = service.getFile(ID);
assertThat(voResult.getFileName())
.isEqualTo(voMock.getFileName());
}
@Test
public void whenGetFileByName_thenReturnFile(){
final String NAME = "test.file";
when(getFileInfoByFileNameProc.get(NAME)).thenReturn(voMock);
FileInfoVO voResult = service.getFile(NAME);
assertThat(voResult.getFileName())
.isEqualTo(voMock.getFileName());
}
@Test
public void whenGetAllFiles_thenReturnAllFiles(){
List<FileInfoVO> list = new ArrayList<>();
list.add(voMock);
list.add(voMock2);
when(getFileInfoProc.get()).thenReturn(list);
List<FileInfoVO> voListResult = service.getAllFiles();
assertThat(voListResult.size())
.isEqualTo(list.size());
}
}
java unit-testing spring mocks
add a comment |
up vote
1
down vote
favorite
I'm working on a new service, for the past year I haven't needed to write tests from scratch. I've either been bug fixing, or adding features that require modification of tests, but not writing everything from scratch.
I need to make sure I'm doing things right. The unit tests below test a service that queries a database for data.
The *Proc files use Springs @Repository
annotation, and each one calls a different stored procedure in the database. For these tests I'm mocking everything. Have I done it correctly? Is there anything I have overlooked? Anything I've possibly missed? The tests all pass when I run them in my IDE or with maven. In this particular instance those method calls simply return the object(s) retrieved from the database, so there isn't any actual business logic in there apart from calling the get()
method from the proc objects that I'm mocking.
Have I done things the correct way?
@RunWith(MockitoJUnitRunner.class)
@SpringBootTest
public class FusServiceImplTest {
@Mock
private GetFileInfoByIdProc getFileInfobyIdProc;
@Mock
private GetFileInfoProc getFileInfoProc;
@Mock
private GetFileInfoByFileNameProc getFileInfoByFileNameProc;
@Mock
FileInfoVO voMock;
@Mock
FileInfoVO voMock2;
@InjectMocks
private FusServiceImpl service;
@Test
public void whenGetFileById_thenReturnFile(){
final Long ID = 99999L;
when(getFileInfobyIdProc.get(ID)).thenReturn(voMock);
FileInfoVO voResult = service.getFile(ID);
assertThat(voResult.getFileName())
.isEqualTo(voMock.getFileName());
}
@Test
public void whenGetFileByName_thenReturnFile(){
final String NAME = "test.file";
when(getFileInfoByFileNameProc.get(NAME)).thenReturn(voMock);
FileInfoVO voResult = service.getFile(NAME);
assertThat(voResult.getFileName())
.isEqualTo(voMock.getFileName());
}
@Test
public void whenGetAllFiles_thenReturnAllFiles(){
List<FileInfoVO> list = new ArrayList<>();
list.add(voMock);
list.add(voMock2);
when(getFileInfoProc.get()).thenReturn(list);
List<FileInfoVO> voListResult = service.getAllFiles();
assertThat(voListResult.size())
.isEqualTo(list.size());
}
}
java unit-testing spring mocks
You can Mock your database at the DAO level, but it probably more productive to actually setup a test database on a loopback address or with a Type 1/2 JDBC driver. tutorialspoint.com/jdbc/jdbc-driver-types.htm Code Review is not the correct place to post this kind of question, it's purpose is to review existing code.
– Martin Spamer
yesterday
Thanks for your response, I'll check that out. I'm not sure of your distinction with existing code though, is it because I'm actively working on it? I was about to commit it and was looking for a code review from here before I pushed it.
– bot_bot
22 hours ago
add a comment |
up vote
1
down vote
favorite
up vote
1
down vote
favorite
I'm working on a new service, for the past year I haven't needed to write tests from scratch. I've either been bug fixing, or adding features that require modification of tests, but not writing everything from scratch.
I need to make sure I'm doing things right. The unit tests below test a service that queries a database for data.
The *Proc files use Springs @Repository
annotation, and each one calls a different stored procedure in the database. For these tests I'm mocking everything. Have I done it correctly? Is there anything I have overlooked? Anything I've possibly missed? The tests all pass when I run them in my IDE or with maven. In this particular instance those method calls simply return the object(s) retrieved from the database, so there isn't any actual business logic in there apart from calling the get()
method from the proc objects that I'm mocking.
Have I done things the correct way?
@RunWith(MockitoJUnitRunner.class)
@SpringBootTest
public class FusServiceImplTest {
@Mock
private GetFileInfoByIdProc getFileInfobyIdProc;
@Mock
private GetFileInfoProc getFileInfoProc;
@Mock
private GetFileInfoByFileNameProc getFileInfoByFileNameProc;
@Mock
FileInfoVO voMock;
@Mock
FileInfoVO voMock2;
@InjectMocks
private FusServiceImpl service;
@Test
public void whenGetFileById_thenReturnFile(){
final Long ID = 99999L;
when(getFileInfobyIdProc.get(ID)).thenReturn(voMock);
FileInfoVO voResult = service.getFile(ID);
assertThat(voResult.getFileName())
.isEqualTo(voMock.getFileName());
}
@Test
public void whenGetFileByName_thenReturnFile(){
final String NAME = "test.file";
when(getFileInfoByFileNameProc.get(NAME)).thenReturn(voMock);
FileInfoVO voResult = service.getFile(NAME);
assertThat(voResult.getFileName())
.isEqualTo(voMock.getFileName());
}
@Test
public void whenGetAllFiles_thenReturnAllFiles(){
List<FileInfoVO> list = new ArrayList<>();
list.add(voMock);
list.add(voMock2);
when(getFileInfoProc.get()).thenReturn(list);
List<FileInfoVO> voListResult = service.getAllFiles();
assertThat(voListResult.size())
.isEqualTo(list.size());
}
}
java unit-testing spring mocks
I'm working on a new service, for the past year I haven't needed to write tests from scratch. I've either been bug fixing, or adding features that require modification of tests, but not writing everything from scratch.
I need to make sure I'm doing things right. The unit tests below test a service that queries a database for data.
The *Proc files use Springs @Repository
annotation, and each one calls a different stored procedure in the database. For these tests I'm mocking everything. Have I done it correctly? Is there anything I have overlooked? Anything I've possibly missed? The tests all pass when I run them in my IDE or with maven. In this particular instance those method calls simply return the object(s) retrieved from the database, so there isn't any actual business logic in there apart from calling the get()
method from the proc objects that I'm mocking.
Have I done things the correct way?
@RunWith(MockitoJUnitRunner.class)
@SpringBootTest
public class FusServiceImplTest {
@Mock
private GetFileInfoByIdProc getFileInfobyIdProc;
@Mock
private GetFileInfoProc getFileInfoProc;
@Mock
private GetFileInfoByFileNameProc getFileInfoByFileNameProc;
@Mock
FileInfoVO voMock;
@Mock
FileInfoVO voMock2;
@InjectMocks
private FusServiceImpl service;
@Test
public void whenGetFileById_thenReturnFile(){
final Long ID = 99999L;
when(getFileInfobyIdProc.get(ID)).thenReturn(voMock);
FileInfoVO voResult = service.getFile(ID);
assertThat(voResult.getFileName())
.isEqualTo(voMock.getFileName());
}
@Test
public void whenGetFileByName_thenReturnFile(){
final String NAME = "test.file";
when(getFileInfoByFileNameProc.get(NAME)).thenReturn(voMock);
FileInfoVO voResult = service.getFile(NAME);
assertThat(voResult.getFileName())
.isEqualTo(voMock.getFileName());
}
@Test
public void whenGetAllFiles_thenReturnAllFiles(){
List<FileInfoVO> list = new ArrayList<>();
list.add(voMock);
list.add(voMock2);
when(getFileInfoProc.get()).thenReturn(list);
List<FileInfoVO> voListResult = service.getAllFiles();
assertThat(voListResult.size())
.isEqualTo(list.size());
}
}
java unit-testing spring mocks
java unit-testing spring mocks
asked yesterday
bot_bot
213110
213110
You can Mock your database at the DAO level, but it probably more productive to actually setup a test database on a loopback address or with a Type 1/2 JDBC driver. tutorialspoint.com/jdbc/jdbc-driver-types.htm Code Review is not the correct place to post this kind of question, it's purpose is to review existing code.
– Martin Spamer
yesterday
Thanks for your response, I'll check that out. I'm not sure of your distinction with existing code though, is it because I'm actively working on it? I was about to commit it and was looking for a code review from here before I pushed it.
– bot_bot
22 hours ago
add a comment |
You can Mock your database at the DAO level, but it probably more productive to actually setup a test database on a loopback address or with a Type 1/2 JDBC driver. tutorialspoint.com/jdbc/jdbc-driver-types.htm Code Review is not the correct place to post this kind of question, it's purpose is to review existing code.
– Martin Spamer
yesterday
Thanks for your response, I'll check that out. I'm not sure of your distinction with existing code though, is it because I'm actively working on it? I was about to commit it and was looking for a code review from here before I pushed it.
– bot_bot
22 hours ago
You can Mock your database at the DAO level, but it probably more productive to actually setup a test database on a loopback address or with a Type 1/2 JDBC driver. tutorialspoint.com/jdbc/jdbc-driver-types.htm Code Review is not the correct place to post this kind of question, it's purpose is to review existing code.
– Martin Spamer
yesterday
You can Mock your database at the DAO level, but it probably more productive to actually setup a test database on a loopback address or with a Type 1/2 JDBC driver. tutorialspoint.com/jdbc/jdbc-driver-types.htm Code Review is not the correct place to post this kind of question, it's purpose is to review existing code.
– Martin Spamer
yesterday
Thanks for your response, I'll check that out. I'm not sure of your distinction with existing code though, is it because I'm actively working on it? I was about to commit it and was looking for a code review from here before I pushed it.
– bot_bot
22 hours ago
Thanks for your response, I'll check that out. I'm not sure of your distinction with existing code though, is it because I'm actively working on it? I was about to commit it and was looking for a code review from here before I pushed it.
– bot_bot
22 hours ago
add a comment |
1 Answer
1
active
oldest
votes
up vote
2
down vote
accepted
Something that stands out is that calling voMock.getFileName()
on mocked instances will always return null as no mock response has been defined. So your validation logic of
assertThat(voResult.getFileName())
.isEqualTo(voMock.getFileName());
essentially winds up being
assertThat(voResult.getFileName())
.isEqualTo(null);
This could end up giving false positives where voResult
is incorrect, but the test passes because the filename is null.
You would need to specify a filename for the response object by calling when(voMock.getFileName()).thenReturn("TestFile")
. This way your test can actually determine that the returned object is the expected one by checking the unique expected value of voMock.getFileName()
.
Alternatively, if the requirement is that the instance returned from the service method is the same instance that the *Proc method returns, just avoid calling getFileName
when you're verifying the test result. You could instead use something like assertSame(voMock, voResult)
to ensure that the instance returned by the service method is the same one that is returned by the *Proc method.
I would always also recommend writing fail/error cases for your class as well. I couldn't give an example without seeing the FusServiceImpl
class, but it can sometimes help with spotting issues like the one I listed above. For instance, if you have a test case like
@Test
public void whenGetFileById_thenReturnFile(){
final Long ID = 99999L;
when(getFileInfobyIdProc.get(ID)).thenReturn(voMock);
FileInfoVO voResult = service.getFile(ID - 1);
assertThat(voResult.getFileName())
.isNotEqualTo(voMock.getFileName());
}
and that test case passes, you know you've probably made a mistake in the test logic. You can also validate that the method fails in the correct manner - does it return an object with null filename? A null return value? Or raise an exception? It's the non-ideal cases that will crash applications in production, so make sure to test for those cases as well.
New contributor
Thanks, I went withassertThat()
in the end, as that makes more sense.
– bot_bot
22 hours ago
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
accepted
Something that stands out is that calling voMock.getFileName()
on mocked instances will always return null as no mock response has been defined. So your validation logic of
assertThat(voResult.getFileName())
.isEqualTo(voMock.getFileName());
essentially winds up being
assertThat(voResult.getFileName())
.isEqualTo(null);
This could end up giving false positives where voResult
is incorrect, but the test passes because the filename is null.
You would need to specify a filename for the response object by calling when(voMock.getFileName()).thenReturn("TestFile")
. This way your test can actually determine that the returned object is the expected one by checking the unique expected value of voMock.getFileName()
.
Alternatively, if the requirement is that the instance returned from the service method is the same instance that the *Proc method returns, just avoid calling getFileName
when you're verifying the test result. You could instead use something like assertSame(voMock, voResult)
to ensure that the instance returned by the service method is the same one that is returned by the *Proc method.
I would always also recommend writing fail/error cases for your class as well. I couldn't give an example without seeing the FusServiceImpl
class, but it can sometimes help with spotting issues like the one I listed above. For instance, if you have a test case like
@Test
public void whenGetFileById_thenReturnFile(){
final Long ID = 99999L;
when(getFileInfobyIdProc.get(ID)).thenReturn(voMock);
FileInfoVO voResult = service.getFile(ID - 1);
assertThat(voResult.getFileName())
.isNotEqualTo(voMock.getFileName());
}
and that test case passes, you know you've probably made a mistake in the test logic. You can also validate that the method fails in the correct manner - does it return an object with null filename? A null return value? Or raise an exception? It's the non-ideal cases that will crash applications in production, so make sure to test for those cases as well.
New contributor
Thanks, I went withassertThat()
in the end, as that makes more sense.
– bot_bot
22 hours ago
add a comment |
up vote
2
down vote
accepted
Something that stands out is that calling voMock.getFileName()
on mocked instances will always return null as no mock response has been defined. So your validation logic of
assertThat(voResult.getFileName())
.isEqualTo(voMock.getFileName());
essentially winds up being
assertThat(voResult.getFileName())
.isEqualTo(null);
This could end up giving false positives where voResult
is incorrect, but the test passes because the filename is null.
You would need to specify a filename for the response object by calling when(voMock.getFileName()).thenReturn("TestFile")
. This way your test can actually determine that the returned object is the expected one by checking the unique expected value of voMock.getFileName()
.
Alternatively, if the requirement is that the instance returned from the service method is the same instance that the *Proc method returns, just avoid calling getFileName
when you're verifying the test result. You could instead use something like assertSame(voMock, voResult)
to ensure that the instance returned by the service method is the same one that is returned by the *Proc method.
I would always also recommend writing fail/error cases for your class as well. I couldn't give an example without seeing the FusServiceImpl
class, but it can sometimes help with spotting issues like the one I listed above. For instance, if you have a test case like
@Test
public void whenGetFileById_thenReturnFile(){
final Long ID = 99999L;
when(getFileInfobyIdProc.get(ID)).thenReturn(voMock);
FileInfoVO voResult = service.getFile(ID - 1);
assertThat(voResult.getFileName())
.isNotEqualTo(voMock.getFileName());
}
and that test case passes, you know you've probably made a mistake in the test logic. You can also validate that the method fails in the correct manner - does it return an object with null filename? A null return value? Or raise an exception? It's the non-ideal cases that will crash applications in production, so make sure to test for those cases as well.
New contributor
Thanks, I went withassertThat()
in the end, as that makes more sense.
– bot_bot
22 hours ago
add a comment |
up vote
2
down vote
accepted
up vote
2
down vote
accepted
Something that stands out is that calling voMock.getFileName()
on mocked instances will always return null as no mock response has been defined. So your validation logic of
assertThat(voResult.getFileName())
.isEqualTo(voMock.getFileName());
essentially winds up being
assertThat(voResult.getFileName())
.isEqualTo(null);
This could end up giving false positives where voResult
is incorrect, but the test passes because the filename is null.
You would need to specify a filename for the response object by calling when(voMock.getFileName()).thenReturn("TestFile")
. This way your test can actually determine that the returned object is the expected one by checking the unique expected value of voMock.getFileName()
.
Alternatively, if the requirement is that the instance returned from the service method is the same instance that the *Proc method returns, just avoid calling getFileName
when you're verifying the test result. You could instead use something like assertSame(voMock, voResult)
to ensure that the instance returned by the service method is the same one that is returned by the *Proc method.
I would always also recommend writing fail/error cases for your class as well. I couldn't give an example without seeing the FusServiceImpl
class, but it can sometimes help with spotting issues like the one I listed above. For instance, if you have a test case like
@Test
public void whenGetFileById_thenReturnFile(){
final Long ID = 99999L;
when(getFileInfobyIdProc.get(ID)).thenReturn(voMock);
FileInfoVO voResult = service.getFile(ID - 1);
assertThat(voResult.getFileName())
.isNotEqualTo(voMock.getFileName());
}
and that test case passes, you know you've probably made a mistake in the test logic. You can also validate that the method fails in the correct manner - does it return an object with null filename? A null return value? Or raise an exception? It's the non-ideal cases that will crash applications in production, so make sure to test for those cases as well.
New contributor
Something that stands out is that calling voMock.getFileName()
on mocked instances will always return null as no mock response has been defined. So your validation logic of
assertThat(voResult.getFileName())
.isEqualTo(voMock.getFileName());
essentially winds up being
assertThat(voResult.getFileName())
.isEqualTo(null);
This could end up giving false positives where voResult
is incorrect, but the test passes because the filename is null.
You would need to specify a filename for the response object by calling when(voMock.getFileName()).thenReturn("TestFile")
. This way your test can actually determine that the returned object is the expected one by checking the unique expected value of voMock.getFileName()
.
Alternatively, if the requirement is that the instance returned from the service method is the same instance that the *Proc method returns, just avoid calling getFileName
when you're verifying the test result. You could instead use something like assertSame(voMock, voResult)
to ensure that the instance returned by the service method is the same one that is returned by the *Proc method.
I would always also recommend writing fail/error cases for your class as well. I couldn't give an example without seeing the FusServiceImpl
class, but it can sometimes help with spotting issues like the one I listed above. For instance, if you have a test case like
@Test
public void whenGetFileById_thenReturnFile(){
final Long ID = 99999L;
when(getFileInfobyIdProc.get(ID)).thenReturn(voMock);
FileInfoVO voResult = service.getFile(ID - 1);
assertThat(voResult.getFileName())
.isNotEqualTo(voMock.getFileName());
}
and that test case passes, you know you've probably made a mistake in the test logic. You can also validate that the method fails in the correct manner - does it return an object with null filename? A null return value? Or raise an exception? It's the non-ideal cases that will crash applications in production, so make sure to test for those cases as well.
New contributor
New contributor
answered yesterday
Samour
362
362
New contributor
New contributor
Thanks, I went withassertThat()
in the end, as that makes more sense.
– bot_bot
22 hours ago
add a comment |
Thanks, I went withassertThat()
in the end, as that makes more sense.
– bot_bot
22 hours ago
Thanks, I went with
assertThat()
in the end, as that makes more sense.– bot_bot
22 hours ago
Thanks, I went with
assertThat()
in the end, as that makes more sense.– bot_bot
22 hours ago
add a comment |
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f208871%2ftesting-a-service-that-makes-database-calls-without-a-database%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
You can Mock your database at the DAO level, but it probably more productive to actually setup a test database on a loopback address or with a Type 1/2 JDBC driver. tutorialspoint.com/jdbc/jdbc-driver-types.htm Code Review is not the correct place to post this kind of question, it's purpose is to review existing code.
– Martin Spamer
yesterday
Thanks for your response, I'll check that out. I'm not sure of your distinction with existing code though, is it because I'm actively working on it? I was about to commit it and was looking for a code review from here before I pushed it.
– bot_bot
22 hours ago