Performing state verification using stubs

Our goal is to test the open_account function with two scenarios, where the check_background function returns either true or false. When a background check is successful, we expect open_account to return :success. Otherwise, it should return :failure.

Using our terminology, open_account is the function under test, while check_background is the collaborator function. It is a bit unfortunate that we can't really control how the collaborator function behaves. In practice, this function may even reach out to a background check service, the working of which we have little influence on. As a matter of fact, we would not want to call the remote service every single time that we test our software.

Now that we have copied from the original CreditApproval module to a new module called CreditApprovalStub, we can move on.

Since we are smart programmers, we can just create a stub that replaces the collaborator function. As functions are first-class in Julia, we can refactor the open_account function so that it can take any background check function from a keyword argument, as follows:

function open_account(first_name, last_name, email; checker = check_background)
checker(first_name, last_name) || return :failure
account_number = create_account(first_name, last_name, email)
notify_downstream(account_number)
return :success
end

The new checker keyword argument takes a function that is used to perform a background check for a customer. We have set the default value to the original check_background function, so it should behave the same as before. Now, the function is more testable.

In our test suite, we can now exercise both execution paths, as follows:

@testset "CreditApprovalStub.jl" begin

# stubs
check_background_success(first_name, last_name) = true
check_background_failure(first_name, last_name) = false

# testing
let first_name = "John", last_name = "Doe", email = "[email protected]"
@test open_account(first_name, last_name, email, checker = check_background_success) == :success
@test open_account(first_name, last_name, email, checker = check_background_failure) == :failure
end

Here, we have created two stubs for background checks: check_background_success and check_background_failure. They return true and false to simulate a successful and failed background check, respectively. Then, when we need to test the open_account function, we can just pass these stub functions via the checker keyword argument.

Let's run the test now:

At this point, we have only enabled the check_background function for stubbing in the open_account function. What if we want to do the same for the create_account and notify_downstream functions? It would be just as easy if we created two more keyword arguments and called it done. This isn't a bad option. However, you may not be very satisfied with the fact that we need to keep changing the code to make new tests. Furthermore, these keyword arguments were added merely for the sake of testing, rather than being a part of the call interface.

In the next section, we will explore the use of the Mocking package, which is an excellent tool for applying stubs and mocks without messing too much with the source code. 

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.139.82.23