void TestPropertyCollection() throw (Exception)
    {
        CellPropertyCollection collection;
        TS_ASSERT_EQUALS(collection.GetSize(), 0u);

        // Test that the CellPropertyRegistry assigned to the CellPropertyCollection defaults to CellPropertyRegistry::Instance().
        TS_ASSERT_EQUALS(collection.GetCellPropertyRegistry(),CellPropertyRegistry::Instance());

        // Add some properties
        NEW_PROP(WildTypeCellMutationState, p_wt_mutation);

        TS_ASSERT_EQUALS(p_wt_mutation->GetIdentifier(), "WildTypeCellMutationState");

        collection.AddProperty(p_wt_mutation);
        NEW_PROP(ApcOneHitCellMutationState, p_apc1_mutation);
        collection.AddProperty(p_apc1_mutation);

        // Test we can't add the same *object* twice
        TS_ASSERT_THROWS_THIS(collection.AddProperty(p_wt_mutation),
                              "That property object is already in the collection.");
        NEW_PROP(WildTypeCellMutationState, p_wt_mutation_2);
        collection.AddProperty(p_wt_mutation_2);
        collection.RemoveProperty(p_wt_mutation_2);

        // Check the contents
        TS_ASSERT_EQUALS(collection.GetSize(), 2u);
        // ...by object
        TS_ASSERT_EQUALS(collection.HasProperty(p_wt_mutation), true);
        TS_ASSERT_EQUALS(collection.HasProperty(p_apc1_mutation), true);
        NEW_PROP(ApcOneHitCellMutationState, p_apc1_mutation_2);
        TS_ASSERT_EQUALS(collection.HasProperty(p_apc1_mutation_2), false);
        // ...by type
        TS_ASSERT_EQUALS(collection.HasProperty<WildTypeCellMutationState>(), true);
        TS_ASSERT_EQUALS(collection.HasProperty<ApcOneHitCellMutationState>(), true);
        TS_ASSERT_EQUALS(collection.HasProperty<ApcTwoHitCellMutationState>(), false);
        // ..by subclass
        TS_ASSERT_EQUALS(collection.HasPropertyType<AbstractCellProperty>(), true);
        TS_ASSERT_EQUALS(collection.HasPropertyType<AbstractCellMutationState>(), true);
        //TS_ASSERT_EQUALS(!collection.HasProperty<AbstractCellMutationState>(), false); <-- This won't compile (yet)
        // ..by iteration
        for (CellPropertyCollection::Iterator it = collection.Begin(); it != collection.End(); ++it)
        {
            TS_ASSERT_EQUALS(collection.HasProperty(*it), true);
            TS_ASSERT((*it)->IsType<WildTypeCellMutationState>() || (*it)->IsType<ApcOneHitCellMutationState>());
            TS_ASSERT_EQUALS((*it)->IsSubType<AbstractCellMutationState>(), true);
        }

        // Remove property
        collection.RemoveProperty<WildTypeCellMutationState>();
        TS_ASSERT_EQUALS(collection.HasProperty<WildTypeCellMutationState>(), false);
        collection.RemoveProperty(p_apc1_mutation);
        TS_ASSERT_EQUALS(collection.HasProperty<ApcOneHitCellMutationState>(), false);
        TS_ASSERT_THROWS_THIS(collection.RemoveProperty<WildTypeCellMutationState>(),
                              "Collection does not contain the given property type.");
        TS_ASSERT_THROWS_THIS(collection.RemoveProperty(p_apc1_mutation),
                              "Collection does not contain the given property.");

        TS_ASSERT_EQUALS(collection.GetSize(), 0u);

        // Get matching properties
        collection.AddProperty(p_wt_mutation);
        collection.AddProperty(p_apc1_mutation);
        CellPropertyCollection mutations = collection.GetPropertiesType<AbstractCellMutationState>();
        TS_ASSERT_EQUALS(mutations.GetSize(), 2u);
        CellPropertyCollection::Iterator it = mutations.Begin();
        TS_ASSERT_EQUALS(collection.HasProperty(*it), true);
        TS_ASSERT_EQUALS((*it)->IsSubType<AbstractCellMutationState>(), true);
        TS_ASSERT( (*it)->IsType<WildTypeCellMutationState>() || (*(++it))->IsType<WildTypeCellMutationState>() );

        CellPropertyCollection wild_types = collection.GetProperties<WildTypeCellMutationState>();
        TS_ASSERT_EQUALS(wild_types.GetSize(), 1u);
        it = wild_types.Begin();
        TS_ASSERT_EQUALS((*it)->IsType<WildTypeCellMutationState>(), true);
        TS_ASSERT( *it == wild_types.GetProperty() );
        TS_ASSERT_THROWS_THIS(collection.GetProperty(),
                              "Can only call GetProperty on a collection of size 1.");
    }