The code snippet you have shown is an excellent unit test, provided that the unit under test is an abstract part combinator, and does not have a more concrete responsibility within the problem domain of the application.
For example, assume that the actual point of this piece of code is to calculate an interest rate. As an implementation detail, this calculation was split into two pieces. A test that is not about interest rates is then a useless test. The shown test would pass whether or not the calculation is correct. It does not ensure that the system behaves as expected, instead it asserts that the system is implemented in a particular manner. In general, such tests are not a good idea. They are fragile, and will break whenever the system is refactored. The blog post is correct in asserting that such tests can cause more work than they are worth.
However, the code is presented without context, and it may well be the entire point of that code to sequentially combine such processors. Such code might be part of an abstract rule engine library, or more generally as part of a Composite Pattern. It is then absolutely correct to test that the two processors are invoked, and are invoked in the correct order. I have written such code and have written such tests without a bad conscience.
It is completely reasonable to use mock objects for this test, since the concrete behaviour of the processor parts is outside of the scope of the unit being tested. According to the book Quality Code by Stephen Vance: “A unit test is a test that verifies the value added by the code under test. Any use of independently testable collaborators is simply a matter of convenience” (Vance 2013, p. 26). Here, the value added by the code is combining two processors into one. It is then sufficient to test what this code does (chaining two sub-processors), and not necessary to also test what these collaborators do (e.g. that the sub-processors perform a correct interest rate calculation). Such tests are also useful, but would be integration tests.
So in either case, the question to be asked is: What is the point of this code, why does it exist? What does this abstraction represent? What interface does it offer to callers? What behaviour is documented? Then test its behaviour, and not the mechanism through which it is implemented.