Unless I am missing something, the way the attributes are set up, when this class is created properly (i.e. ref new in C++/CX, new in C#/JS, or RoActivateInstance()), TestClass::TestMethod can only return "MTA".

The ThreadingModel attribute specifies where the class is loaded when activated: only in a user-interface thread (STA) context, only in a background thread (MTA) context, or in the context of the thread that creates the object (Both).

Unless I am misinterpreting this [Threading(ThreadingModel::MTA)] means that the class can only be activated in an MTA thread. Before, in good old COM days, trying to activate MTA class in STA thread caused COM to create MTA thread, activate the class there,
and marshal the interface back to STA thread.

Since I specifically put [MarshalingBehavior(MarshalingType::Standard)] there, the marshaling behavior is one of standard COM marshaler, which is well-known:

In the case of STA->MTA call, system should have created MTA, created the object in that MTA, and marshaled the TestMethod() call. It is just very surprising it does not happen, despite the attributes propagating correctly to the manifest.

The attribute will affect how the COM creates the control (e.g. via
CoCreateInstanceFromApp or
RoActivateInstance). In your code snippet you new the class instead of going through COM. This creates ThisClass as a normal C++ class, not as a COM object, and so no marshaling is done when calling TestMethod. It gets called on the current thread in whichever
apartment the thread runs on.

Apologies for not being more clear. My second code example (the one that creates the class with "new") is in *JavaScript*. It cannot create the class as a "normal C++ class", it has to go through WinRT.