Modifications for Testability

Before we dive into writing test cases, we need to adjust our marketplace code to facilitate testing. To enhance testability, we've introduced auxiliary functions and modifications:

  1. Helper & View Functions
  2. Internal Layer for Entry Functions

Add Helper & View functions:

  • borrow_listing
    • This is a helper function to borrow Listing object resource in the object from the global storage. This also checks that the Listing resource exists within the provided object address. This is defined as a friend function so that our test module test_list_and_purchase can call this function.

// Helper function
inline fun borrow_listing(object: Object<Listing>): &Listing acquires Listing {
let obj_addr = object::object_address(&object);
assert!(exists<Listing>(obj_addr), error::not_found(ENO_LISTING));
borrow_global<Listing>(obj_addr)
}

  • price
    • This is a view function to read price field of the FixedPriceListing resource from the object that the Object<Listing> object reference points to.
  • listed_object
    • This is a view function to get the listed token object from the object that the Object<Listing> object reference points to.

// View functions
#[view]
public fun price<CoinType>(
object: Object<Listing>,
): Option<u64> acquires FixedPriceListing {
let listing_addr = object::object_address(&object);
if (exists<FixedPriceListing<CoinType>>(listing_addr)) {
let fixed_price = borrow_global<FixedPriceListing<CoinType>>(listing_addr);
option::some(fixed_price.price)
} else {
// This should just be an abort but the compiler errors.
assert!(false, error::not_found(ENO_LISTING));
option::none()
}
}
#[view]
public fun listed_object(object: Object<Listing>): Object<ObjectCore> acquires Listing {
let listing = borrow_listing(object);
listing.object
}

Add Internal layer for Entry Functions:

  • list_with_fixed_price_internal
    • This function sits behind the list_with_fixed_price entry function, allowing for the evaluation and testing of the Listing object. This is crucial since entry functions can't return values, so this internal function provides a workaround for unit testing.

inline fun fixed_price_listing(
seller: &signer,
price: u64
): (Object<Token>, Object<Listing>) {
let token = test_utils::mint_tokenv2(seller);
fixed_price_listing_with_token(seller, token, price)
}
inline fun fixed_price_listing_with_token(
seller: &signer,
token: Object<Token>,
price: u64
): (Object<Token>, Object<Listing>) {
let listing = list_and_purchase::list_with_fixed_price_internal<AptosCoin>(
seller,
object::convert(token), // Object<Token> -> Object<ObjectCore>
price,
);
(token, listing)
}