I am trying to test an http server functionality and this is the first time I get exposed to the notions of mocks, stubs and fakes. I'm reading this book that it says mocking is describing the state of a complex object at a certain moment, like a snapshot, and testing the object as it is actually the real one. right? I understand this. what I don't understand is what is the point of writing unit tests and assertions of certain cases that we fully describe in the mock object. If we set the expectations of arguments and return values on the mocking object, and we test for those exact values, the test will always pass. Please correct me. I know I am missing something here.
Mocks, Stubs or anything similar serves as a substitute for the actual implementation.
The idea of mocks is basically to test a piece of code in a isolated environment, substituting the dependencies for a fake implementation. For example, in Java, suppose we want to test the PersonService#save method:
class PersonService {
PersonDAO personDAO;
// Set when the person was created and then save to DB
public void save(Person person) {
person.setCreationDate(new Date());
personDAO.save(person);
}
}
A good aproach is creating a unit test like this:
class PersonServiceTest {
// Class under test
PersonService personService;
// Mock
PersonDAO personDAOMock;
// Mocking the dependencies of personService.
// In this case, we mock the PersonDAO. Doing this
// we don't need the DB to test the code.
// We assume that personDAO will give us an expected result
// for each test.
public void setup() {
personService.setPersonDao(personDAOMock)
}
// This test will guarantee that the creationDate is defined
public void saveShouldDefineTheCreationDate() {
// Given a person
Person person = new Person();
person.setCreationDate(null);
// When the save method is called
personService.save(person);
// Then the creation date should be present
assert person.getCreationDate() != null;
}
}
In another words, you should use mock to substitute dependencies of your code to an "actor" that can be configured to return an expected result or assert some behaviours.
Related
I got off from writing basic unit tests using JUnit for simple methods that adds two numbers. I can verify the result by using the assert* family of function calls. Now I want to unit test a Spring Boot controller.
Here is the example of the unit test class -
public class MyJunitTest {
private MockMvc mockMvc;
#Mock
private MyService service;
#InjectMocks
private MyController controller;
#Before
public void init() {
MockitoAnnotations.initMocks(this);
}
#Test
public void unitTestGetAssessmentDetails() {
when(service.getTest(Someobject.class)).thenReturn(customObjectWithValues);
Results results = controller.getCall(someRequestObject);
assertEquals(results, someOtherObjectPrefilledWithValues);
}
}
My question is, if I know the values set in customObjectWithValues, then someOtherObjectPrefilledWithValues is also set by me, then assertEquals will always give a pass to the test, right? It's essentially testing if 1==1 kind of test. So what is the point of doing these unit tests? I know that the service object should not connect to the actual DB, and hence we are mocking it. So what is the point of doing these tests? Am I missing the bigger picture here as to how to view unit tests?
P.S. - Please feel free to remove this question if it violates the rules of this forum.
Your test verifies that getCall returns the expected results;
this is a black box test.
Since you are writing a unit test,
this is only sufficient to "pretend" to perform a unit test.
This technique is common in firms that conflate code quality with
unit test code coverage.
A better technique is to identify the steps that will be taken by the controller class and to verify that each was executed (perhaps in the correct order, as well).
I will assume that MyController.getCall looks something like this:
#Autowired
private MyService myService;
public BlammyReturnValueType getCall(final BlammyRequestType request)
{
final BlammyReturnValueType returnValue;
returnValue = myService.someServiceMethod(request);
return returnValue;
}
In this case,
I would add the following to the unitTestGetAssessmentDetails test method:
... The current stuff including the assert.
Mockito.verify(service, times(1)).someServiceMethod(customObjectWithValues);
This will confirm that the service method was called exactly one time,
which is correct in this example.
Ok so, unit testing is more about testing the logic written in your function/controller/service. Now, your function might be very simple or it might be very complex. For ex, your function might be taking and UserId in request, connect to database, gets the data and return it and since you are mocking the database connection, you might feel like if you are passing the mocked object as database response, you will obviously get the same response, so what's the point of testing. It might seem correct to not test at all in this case. But let me give you another example, say you have a very complex function, which takes some UserId, gets the whole year data of users banking history, cumulates it and calculates the amount user earned for this year. Now, think how complex this function is. Now since you have mocked the DB connection you will pass in some data, a lot of computation goes on inside and gives the user an amount earned as Interest on saving. Now, for a given mocked data, you know the answer should come as some X amount. Now, over the time, someone made a mistake (maybe subtracted something which was needed to be added). Now, when you run the test. This test will fail and you know something is wrong with logic. Not here you are not directly expecting the output to be equal to your mocked data, some computation has been done over the data, so to verify after each change that function logic is correct, you need to write a unit test to verify it. Now if you see here, your are not testing 1==1 but something different. This is why people write unit tests, to check their logic inside a unit of code.
Hope this helps.
Usually we have 3 layers which are Controller, Service, Repository (DAO if you prefer). I usually do not test controllers because I do not put any logic in them, I just define the endpoint and call the service. The service is what I heavily unit test so you would inject the mocks into your service. Then you would mock your Repository so it wouldn't try to connect to a database.
#InjectMocks
private MyService service;
#Mock
private MyRepository myrepo
#Test
public void unitTestGetAssessmentDetails() {
when(myrepo.find(someInt)).thenReturn(customObjectWithValues);
Results results = service.serviceMethod(someRequestObject);
assertEquals(results, someOtherObjectPrefilledWithValues);
}
Since controllers are supposed to have no logic they shouldn't need unit test because as you correctly say it's a 1==1 test. But they would be tested by integration tests
As a person has no experience before in unit testing and mocking, I followed beginner tutorials about JUnit with Mockito and I do some practice.
Now, I need to unit test some class methods which do basic database operations on a MySQL database. I don't want to make real changes on the database.
In my code:
#InjectMocks private DBConnection dbConnection;
#Mock private DBConnection mockDBConnection;
#Test
public void testDropTable() {
Mockito.when(mockDBConnection.dropTable()).thenReturn(0);
// dropTable() returns 0 if table dropped
int result = dbConnection.dropTable();
Assert.assertEquals(result, 0);
}
To verify(with assertEquals() ) result of the test, I am calling real dropTable() method, and it really drops table( Actually it is obvious, because I'm calling on real DBConnection instance)
Is there anyway to verify the methods like that, without accessing the real database? Or did I misunderstand the concept of Unit Testing and Mocking?
Imagine the following... You have two cars, one is a real car, another is a fake (mock) car. Now you get into the real car and drive off. Why do you expect not to move? You didn't do anything with the fake car, so even if you told it "Do not move if I start driving", this doesn't change the fact that the real car WILL move when you drive off.
Same thing here, you created a fake DBConnection and a real one. The real one will do whatever the real one does. The fake one can be configured to do different stuff, like you did with Mockito.when(...). But that doesn't change the behavior of the real one.
Your test is effectively meaningless, because your only choice here is to get rid of the mock, because it doesn't serve any meaningful purpose. You do not test a mock. What for? That's like creating a fake car and testing that - it doesn't tell you anything about the real car. You do not need to test the fake car to find out that it will do X if you told it to do X in that test.
There are two ways you can test your DBConnection class:
a) You can connect it to a database and check that it does what it should. This would, of course, be an integration test and not a unit test anymore. In some cases you can use a in-memory database like HSQLDB to speed up this test. But at least in the end you can be reasonably sure that your code does what it is supposed to be doing.
b) IF and only IF DBConnection has some objects internally that do the actual talking to the database, you can, perhaps, mock those and then test DBConnection. Of course, this only moves your problem to another layer, because then you aren't sure that those objects work - you will only know that DBConnection works IF those objects work. While this is good to know, it does not answer the question if your db code will work in the end.
In the end, you can only test db connections completely by connecting to a db. Everything else is not a complete test.
Why not consider using an in-memory database for your unit tests. Maybe using a DAO pattern to easily switch between real and in-memory.
Keep the actual database interaction layer thin as possible to ensure you abstract your logic away in separate classes, this makes testing much easier, as in this case you can mock the DB object and focus on testing your logic.
Also decide what you are testing, most likely you want to test your logic, not the logic of the 3rd party database connector, so focus your tests on that.
Consider a suite of Integration or System tests to test the applications features against a real database, should you require this level of testing, but for unit tests, in-memory should be fine.
The overall confidence of your app can be achieved using be a combination of unit and integration tests.
For the #Florian Schaetz's comment, do I need to do something like that:
AuthenticatorApplicationInterface.java
public interface AuthenticatorInterface {
public boolean authenticateUser(String username, String password) throws EmptyCredentialsException;
}
AuthenticatorApplication.java
public class AuthenticatorApplication {
private AuthenticatorInterface authenticator;
public AuthenticatorApplication(AuthenticatorInterface authenticator) {
this.authenticator = authenticator;
}
public boolean authenticate(String username, String password) throws NotAuthenticatedException {
boolean authenticated;
authenticated = this.authenticator.authenticateUser(username, password);
return authenticated;
}
}
AuthenticatorApplicationTest.java
public class AuthenticatorApplicationTest {
#Test
public void testAuthenticate() throws EmptyCredentialsException {
AuthenticatorInterface authenticatorMock;
AuthenticatorApplication authenticator;
String username = "username";
String password = "noncorrectpassword";
authenticatorMock = Mockito.mock(AuthenticatorInterface.class);
authenticator = new AuthenticatorApplication(authenticatorMock);
when(authenticatorMock.authenticateUser(username, password)).thenReturn(false);
boolean actual = authenticator.authenticate(username, password);
assertFalse(actual);
}
}
I am trying to write a Unit Tests to a legacy code using Mockito.
But I am not able to understand how do I mock it. Can some please help.
The real problem I am facing is actually I am not able to decide how to make a decision on what exactly is to be mocked? Below is the code. I have looked at numerous videos on YouTube and read many Mockito Tutorials but all of them seem to be guiding mostly about how to use the Mockito Framework.
The basic idea of what to Mock is still unclear. Please guide if you have a better source. I do understand that the code showed below does not really showcase the best coding practice.
public class DataFacade {
public boolean checkUserPresent(String userId){
return getSomeDao.checkUserPresent(userId);
}
private SomeDao getSomeDao() {
DataSource dataSource = MyDataSourceFactory.getMySQLDataSource();
SomeDao someDao = new SomeDao(dataSource);
}
}
Well, a Unittest, as the name implies, tests a unit. You should mock anything that isn't part of that unit, especially external dependencies. For example, a DAO is normally a good example for something that will be mocked in tests where the class under tests uses it, because otherwise you would really have actual data access in your test, making it slower and more prone to failure because of external reasons (for example, if your dao connects to a Datasource, that Datasource's target (for example, the database) may be down, failing your test even if the unit you wanted to test is actually perfectly fine). Mocking the DAO allows you to test things independently.
Of course, your code is bad. Why? You are creating everything in your method by calling some static factory method. I suggest instead using dependency injection to inject the DAO into your facade, for example...
public DataFacade(SomeDao someDao) {
this.someDao = someDao;
}
This way, when instantiating your DataFacade, you can give it a dao, which means, in your test you can give it a mock, for example...
#Test
public void testSomething() {
SomeDao someDaoMock = Mockito.mock(SomeDao.class);
DataFacade toTest = new DataFacade(someDaoMock);
...now you can prepare your mock to do something and then call the DataFace method
}
Dependency injection frameworks like Spring, Google Guice, etc. can make this even easier to manage, but the first step is to stop your classes from creating their own dependencies, but let the dependencies be given to them from the outside, which makes the whole thing a lot better.
You should "mock" the inner objects that you use in your methods.
For example if you write unit tests for DataFacade->checkUserPresent, you should mock the getSomeDao field.
You have a lot of ways to do it, but basically you can make getSomeDao to be public field, or get it from the constructor. In your test class, override this field with mocked object.
After you invoke DataFacade->checkUserPresent method, assert that checkUserPresent() is called.
For exmaple if you have this class:
public class StudentsStore
{
private DbReader _db;
public StudentsStore(DbReader db)
{
_db = db;
}
public bool HasStudents()
{
var studentsCount = _db.GetStudentsCount();
if (studentsCount > 0)
return true;
else
return false;
}
}
And in your test method:
var mockedDb = mock(DbReader.class);
when(mockedDb.GetStudentsCount()).thenReturn(1);
var store = new StudentsSture(mockedDb);
assertEquals(true,store.HasStudents());
When people say "test only one thing". Does that mean that test one feature at a time or one scenario at a time?
method() {
//setup data
def data = new Data()
//send external webservice call
def success = service.webserviceCall(data)
//persist
if (success) {
data.save()
}
}
Based on the example, do we test by feature of the method:
testA() //test if service.webserviceCall is called properly, so assert if called once with the right parameter
testB() //test if service.webserviceCall succeeds, assert that it should save the data
testC() //test if service.webserviceCall fails, assert that it should not save the data
By scenario:
testA() //test if service.webserviceCall succeeds, so assert if service is called once with the right parameter, and assert that the data should be saved
testB() //test if service.webserviceCall fails, so again assert if service is called once with the right parameter, then assert that it should not save the data
I'm not sure if this is a subjective topic, but I'm trying to do the by feature approach. I got the idea from Roy Osherove's blogs, but I'm not sure if I understood it correct.
It was mentioned there that it would be easier to isolate the errors, but I'm not sure if its overkill. Complex methods will tend to have lots of tests.
(Please excuse my wording on the by feature/scenario, I'm not sure how to word them)
You are right in that this is a subjective topic.
Think about how you want this method to behave, not just on how it's currently implemented. Otherwise your tests will just mirror the production code and will break everytime the implementation changes.
Based on the limited context provided, I'd write the following (separate) tests:
Is the webservice command called with the expected data?
If the command returns successfully, is the data saved? Don't overspecify the arguments provided to your webservice call here, as the previous test covers this.
If it's important that the data is not saved when the command returns a failure, I'd write a third test for this. If it's not important, I wouldn't even bother.
You might have heard the adage "one assert per test". This is good advice in general because a test stops executing as soon as a single assert fails. All asserts further down are not executed. By splitting up the asserts in multiple tests you will receive more feedback when something goes wrong. When tests go red, you know exactly all the asserts that fail and don't have to run through the -fix assertion failure, run tests, fix next assertion failure, repeat- cycle.
So in the terminology you propose, my approach would also be to write a test per feature of the method.
Sidenote: you construct your data object in the method itself and call the save method of that object. How do you sense that the data is saved in your tests?
I understand it like this:
"unit test one thing" == "unit test one behavior"
(After all, it is the behavior that the client wants!)
I would suggest that you approach your testing "one feature at a time". I agree with you where you quoted that with this approach it is "easier to isolate the errors". Roy Osherove really does know what he is talking about especially when it comes to TDD.
In my experience I like to focus on the behaviors that I am trying to test (and I am not particularly referring to BDD here). Essentially I would test each behavior that I am expecting from this code. You said that you are mocking out the dependencies (webservice, and data storage) so I would still class this as a unit test with the following expected behaviors:
a call to this method will result in a particular call to a web service
a successful web service call will result in the data being saved
an unsuccessful web service call will result in the data not being saved
Having tests for these three behaviors will help you isolate any issues with the code immediately.
Your tests should also have no dependency on the actual code written to achieve the behavior. For example, if my implementation called some decorator internal to my class which in turn called the webservice correctly then that should be no concern of my test. My test should only be concerned with the external dependencies and public interface of the class itself.
If I exposed internal methods of my class (or implementation details, such as the decorator mentioned above) for the purposes of testing its particular implementation then I have created brittle tests that will fail when the implementation changes.
In summary, I would recommend that your tests should lock down the behavior of a class and isolate failures to identify the 'unit of behavior' that is failing.
A unit test in general is a test that is done without a call to database or file system or even to that effect doesnot call a webservice either. The idea of a unit test is that if you did not have any internet connection you should be able to unit test. So having said that , if a method calls a webservice or calls a database, then you basically are expected to mock the responses from an external system. You should be testing that unit of work only. As mentioned above by prgmtc on how you should be asserting one assert per method is the way to go.
Second, if you are calling a real webservice or database etc, then consider calling those test as integrated or integration test depending upon what you are trying to test.
In my opinion to get the most out of TDD you want to be doing test first development. Have a look at uncle Bobs 3 Rules of TDD.
If you follow these rules strictly, you end up writing tests that generally only have a single assert statements. In reality you will often find you end up with a number of assert statements that act as a single logical assert as it often helps with the understanding of the unit test itself.
Here is an example
[Test]
public void ValidateBankAccount_GivenInvalidAccountType_ShouldReturnValidationFailure()
{
//---------------Set up test pack-------------------
const string validBankAccount = "99999999999";
const string validBranchCode = "222222";
const string invalidAccountType = "99";
const string invalidAccoutTypeResult = "3";
var bankAccountValidation = Substitute.For<IBankAccountValidation>();
bankAccountValidation.ValidateBankAccount(validBankAccount, validBranchCode, invalidAccountType)
.Returns(invalidAccoutTypeResult);
var service = new BankAccountCheckingService(bankAccountValidation);
//---------------Assert Precondition----------------
//---------------Execute Test ----------------------
var result = service.ValidateBankAccount(validBankAccount, validBranchCode, invalidAccountType);
//---------------Test Result -----------------------
Assert.IsFalse(result.IsValid);
Assert.AreEqual("Invalid account type", result.Message);
}
And the ValidationResult class that is returned from the service
public interface IValidationResult
{
bool IsValid { get; }
string Message { get; }
}
public class ValidationResult : IValidationResult
{
public static IValidationResult Success()
{
return new ValidationResult(true,"");
}
public static IValidationResult Failure(string message)
{
return new ValidationResult(false, message);
}
public ValidationResult(bool isValid, string message)
{
Message = message;
IsValid = isValid;
}
public bool IsValid { get; private set; }
public string Message { get; private set; }
}
Note I would have unit tests the ValidationResult class itself, but in the test above I feel it gives more clarity to include both Asserts.
I am just getting involved in Moq and unit testing, so forgive me if this seems obvious (a quick search through SO didn't show me anything like this).
I have an interface with the following proposed member:
void AddFeed(Feed feed);
That I would like to write a unit test for this functionality. The test class has a Moq Repository declared as follows:
static IFeedRepository MockFeedsRepository(params Feed[] feeds)
{
var mockFeedsRepository = new Moq.Mock<IFeedRepository>();
mockFeedsRepository.Expect(x => x.Feeds).Returns((feeds.AsQueryable));
return mockFeedsRepository.Object;
}
How should the mock repository declaration be modified to include this new desired behavior or should I create a different Moq (and just how would that be done).
My assumption is that after creating the mock, deriving the unit test will be much easier but hints are greatly appreciated.
Many thanks,
KevDog
I'm also assuming that you would use the AddFeed method like this
Feed myNewFeed = new Feed();
feedRepository.Add(myNewFeed);
and that you're not using it like this (which is poor design)
IFeedRepository feedRepository = new FeedRepository();
Feed myNewFeed = new Feed(feedRepository);
...
myNewFeed.Save();
I'm going to guess that you would want to then have a test something like this:
[Test]
public void TheTest()
{
IFeedRepository repository = MockFeedsRepository({feed1, feed2, feed3});
Feed newFeed = new Feed();
repository.Add(newFeed);
Assert.AreEqual(4,repository.Count());
}
If that's the case then the test isn't actually testing anything other than your implementation of a mock in-memory repository. Is that what you really need to be doing?
I'd suggest that what you want to be doing is testing the L2Sql implementation of the repository instead, or testing how classes interact with the IFeedRepository interface.
And if you want to test the usage of the IFeedRepository interface then just do something simple like
[Test]
public void TheTest()
{
IFeedRepository repository = Moq.Mock<IFeedRepository>();
Feed newFeed = new Feed();
repository.Expect(r => r.Add(newFeed)); //no return as it's a void method
//repository.Expect(r => r.Add(newFeed)).Throws(new ApplicationException()); --Test handing of exceptions
//Code to hit the .Add() method
//Assert the Add method was called.
}
For tips on asserting if a method was called, see Using Moq to determine if a method is called
I hope that helps