In my unit tests, I want to provide complete isolation between tests. Thus, any entities created in one test method should not exist in another test method. For performance reasons, it would be ideal to be able to create one domain before any tests are executed (i.e. in a class decorated by SetUpFixture attribute... or, in your "AutoBuildTest" example, in the TestFixtureSetUp method). I tried to create an outer transaction inside my test methods and rollback the transaction at the end of the test. The problem with this approach is that business rules are not enforced within the test method. For example, if I create a unique index on MyEntity.Name property, then I should not be able to create 2 instances of MyEntity with the same Name value. Unfortunately, using this approach, I can violate this rule, and an exception is never thrown. Is there a suggested approach? I think isolation is absolutely critical in order to be able to write proper unit tests. Updated at 18.02.2010 22:32:12Obviously, creating a domain for each test method is not an option (even using in-memory storage, because each domain build process takes a few seconds). I should be able to create one domain that is shared between all tests. Any changes made in a test method should be validated (validation aspects, onvalidate method, index uniqueness constraints, etc.). Then, at the completion of the test, these changes should be rolled back to provide isolation for the next test method. Updated at 19.02.2010 0:10:34Alex, Here's what I'm doing... similar to the AutoBuildTest you guys provide in your DO4 project templates. AutoBuildTest class <-- all test fixtures inherit from this classTestFixtureSetUp method: Build a domain TestFxitureTearDown method: dispose of domain SetUp method: A) open session B) open "isolation" transaction scope TearDown method: A) rollback "isolation" transaction scope B) dispose session SomeTest class <-- inherits from AutoBuildTest classSomeTestMethod1: a) open nested transaction scope with TransactionOpenMode.New, b) create/modify entities, c) make asserts, d) commit nested transaction via transactionScope.Complete() OK, so what I was doing actually does work. I had just forgotten to apply one of the nUnit attributes to a setup method. I don't use Session.Persist(). Do you think I need to? Thank you! This thread was imported from our support forum. The original discussion may contain more detailed answer. |
A bunch of advices:
> OK, so what I was doing actually does work. I had just forgotten to apply one of the nUnit attributes to a setup method. I don't use Session.Persist(). Do you think I need to? No, you shouldn't - I forgot that Session.Persist is inevitably called on nested transaction commit (as well as on its opening). If this isn't done, we're moving a part of operations that are considered as performed inside it to outer transaction, which is absolutely incorrect. |