heroes, by writing automated tests for it. We will also set up configurable environments for our application.
heroesapplication needs to be able to configure the username, password, host port and name of the database it uses. Open the file
config.yaml, which is empty, and enter the following key-value pairs:
lib/channel.dart, declare a new class at the bottom of the file:
Configurationsubclass declares the expected properties of a configuration file.
HeroConfighas one property named
database- this matches the name of our top-level key in
DatabaseConfigurationis a built-in configuration type that has properties for
databaseName. We can load
HeroConfigbecause they have the same structure and all of the key names match the property names in our configuration types.
config.yamland use its values to set up our database connection by replacing the
optionsproperty that has the command-line arguments that started the application. By default, the value of
config.yaml(it corresponds to
conduit serve). When
config.yamlis read, its values are read into a
HeroConfigand are used to configure our database connection.
config.yamlinto version control because it contains sensitive information. However, it is important to check in a configuration source file. A configuration source file has the same structure as
HeroConfig, but it has values for your test environment - both locally and with continuous integration tools. It is also used as a template for your deployed configuration files.
$prefix as a value, e.g.
config.src.yaml, and one currently exists as an empty file in your project. Enter the following configuration into this file:
testwas already added to your
pubspec.yamlfile as a test dependency by the template generator.
mainfunction. In this function, the
testfunction is called multiple times to register expectations. A test passes if all of your expectations are met. An example Dart test looks like this:
config.src.yaml, we target the database
dart:[email protected]:5432/dart_test. This is a 'special' database that is used by all Conduit applications for automated testing (by default). When your application is tested, its tables are temporarily added to this database and then discarded after tests complete. This means that no data is stored in between test runs.
_test.dartand must be in the
test/directory of your project, or it won't be run.
installmethod. This harness can then send requests to your application, and you can expect that the response is correct. Add a test to the main function that makes sure we get back a 200 OK when we call
Agentthat can send requests to the application it started. Methods like
posttake a path (and optionally headers and a body) and return a response object. This object is used in
expectResponseto validate the status code and other values. Tests in Conduit are written in this way: make a request, expect that the response is intended.
TestHarnessORMMixinand override two methods:
resetData. This method deletes everything from the test database and uploads the schema in a pristine state. By calling this method in
onSetUp, our test harness will reset data before each test.
-tcommand-line argument with
conduit createallows you to select a template. Templates like
db_and_authhave a test harness that already mixes in
Run tests in 'hero_controller_test.dart'. A panel will appear that shows the results of your tests. You'll see a green checkmark next to the test in this panel to show that your test succeeded. If your test did not succeed, the reason will be printed to the console. If your test failed because of an error in your code, you will also be able to see the stack trace of the error.
pub run testfrom your project's directory. You can re-run a test with the green play button at the top right corner of the screen, or the keyboard shortcut associated with it (this shortcut varies depending on your installation).
idgreater than 0, and a
namethat is a string. When expecting a body value, the body is first decoded from its content-type before the expectation. In practice, this means that your JSON response body is deserialized into an object or list. Your expectations of the body are built from Dart objects like
Objectthat deserialized from JSON.
package:matcher. There are many types of matchers for all kinds of scenarios, and
package:conduit_testincludes Conduit-specific matchers. See the conduit_test API Reference for all Conduit matchers.
hero.dartat the top of the file!
POST /heroes. In the first test, we'll make a mistake on purpose to see how tests fail. Add the following test:
nameis a unique property of a hero. Notice that the first request didn't fail, even though we had created a 'Fred' hero in the previous test - that's because we reset the database for each test in our harness.