# Unit Testing

If you wish to write Unit Tests for your application which uses AWFPY, you can do so using the MockAWFClient.

# ๐Ÿงค What is a Mock?

A mock object substitutes and imitates a real object within a testing environment. In AWFPY's case, it substitutes the client requests while still checking the correctness of your requests and returning proper objects back to your tests. Mock objects can also be used to assess the usage of the API, such as how many times you have called a method, or which parameters you used to do so.

# ๐Ÿงฐ Mock Client

You can substitute the mock client and use it as you would the real client.

# ๐Ÿ”Œ Connection

You can use the mock client with either a decorator for your test functions, or as a context manager. They are both functionally identical.

from awfpy.test.MockAWFClient import MockAWFClient

To use it as a decorator, you must supply a client parameter to your function. Please note that the decorator must be called, like a function, to work properly.

@MockAWFClient()
def test_mock_decorator(self, client):
    client.get_workflow('tutorial')

The context manager can be used if you only want to make use of client in an indented block instead of the whole function.

def test_mock_context_manager(self):
    with MockAWFClient() as client:
        client.get_workflow('tutorial')

# ๐Ÿงช Usage & Testing

You can use this mock to do the same operations as on the client, but with no side effects. The mocks have runtime validation for parameters, just like the real client, and they have the same return types, with mock objects for get methods.

@MockAWFClient()
def test_mock(self, client):
    # Assert same instance type
    assert isinstance(client, AWFClient)

    # Get a workflow object
    client.get_workflow('tutorial')

    # Assert method called
    client.get_workflow.assert_called()

    # Asserting method called with specific parameters
    client.get_workflow.assert_called_with('tutorial')

    # Assert invalid parameters
    with self.assertRaises(TypeError):
        # Will raise TypeError, because we are creating a Resource with a Run object
        client.create_resource(mockRun)