Reputation: 405
Let's suppose you want to create unit tests for a game.
You have the Player
class, which has a local variable of the World
class (instantiated by the construtor) and the World
object has an open connection to the database.
So player.breakBlock()
method would call world.breakBlockAt(x,y,z)
and world.breakBlockAt(int x, int y, int z)
method would perform changes to the database and return the result.
In cases like this where you have complex "object dependencies", what would be the best way to perform testing?
Currently I'm basically starting the whole game environment, with a test database, spawning a fake Player and using it for the testing.
Upvotes: 5
Views: 2671
Reputation: 25873
Depends on what type of testing you want to perform:
Note that mocking usually involves using a mocking library (e.g. Mockito) to make the mocking easier.
Also note that if you're using dependency injection, the testability of the code is much better since you can inject mocks as well.
More detailed information about test types
Upvotes: 3
Reputation: 1502
To test your Player
class without a database, you could use a mocking framework like EasyMock or Mockito to create a mock of your World
object, pre-record the methods you expect your Player
class to call and then verify later that the method was actually called.
You can also let your mock objects intercept the method call and replace it with custom logic. You could for example delegate the call breakBlockAt
to a method that modifies a HashMap
instead of an actual database. And the returned value could then behave differently depending on what previous calls already did to the HashMap
.
Of course you should still have a separate test case for your World
class as well, to actually test the logic that works with the database (but without adding the complexity of the Player
class on top). This is basically an integration test where you make sure that the JDBC statements or JPA objects result in valid SQL that works when used with the database dialect of your choice.
A library like Testcontainers can be used to set up an empty database in a Docker container from within your unit test. The only requirement is that your test environment has Docker running and ready for execution.
Upvotes: 3
Reputation: 12953
The idea in unit tests is that on each test, you test only one component of your code.
Meaning, on World
's test, I'd mock the database connection, and write tests on world.breakBlockAt(x,y,z)
where I mock the DB to do various cases.
The idea here is not to test the DB, but:
- that your code passes the correct input to the db
- that your code handles the various results as expected.
- that your code handles correctly all kind of responses from db (for example, handles exceptions correctly)
Same goes to Player
- on this one you should mock world, and check that your code in player passes the correct values to World, and handles ok the response from it
Upvotes: 2