After several years of following the bad practice handed down from \'architects\' at my place of work and thinking that there must be a better way, I\'ve recently been reading u
What you mention is called state testing. There's also behavior testing. The techniques used for that are Dependency Injection, Inversion Of Control, and Mocking:
All side effects of your class are implemented as method invocations on its "dependencies" -- i.e. objects supplied from the outside, usually in constructor. Then, in your unit-test, you supply a fake object instead of a real one. The fake object can remember if its' certain method was called, and that's what you assert in your test.
There exist number of Mocking Frameworks that automate mock object creation by dynamically generating classes that implement a given interface. Most popular are Rhino.Mocks and Moq.
If you're really going to go as far as to forbid retrieval of state, then you will be limited to behavioural testing, probably through a mocking framework such as TypeMock, which has the power to track the behaviour of your object. If you are able to do pure BDD, then theoretically you can assert the correctness of your entire system just by the way it's behaving.
In practice, I've found BDD to be more brittle in a lot of cases than just stateful testing. While some people might call for a certain theory, it only works if it works for you. State-based testing still makes up 90% of all the unit tests we write, and we're well aware of BDD on our team.
Do what works best for you.