I have the following task and I have not found a good answer. In this case, I use the Mocking framework (JMock) to isolate the tests from the database code. I make fun of access to classes that are related to the database logic, and separately test the database classes using DBUnit.
The problem I am facing is that I notice a pattern where logic is conceptually duplicated in several places. For example, I need to find that the value in the database does not exist, so I could return null from the method in this case. So I have a database access class that interacts with the database and returns zero accordingly. Then I have a business logic class that gets zero from the layout, and then is checked to act accordingly if the value is null.
Now, what if in the future the behavior should change and return null, it no longer fits, say, because the state has become more complicated, so I will need to return an object that says that the value does not exist, and some additional fact from the database.
Now, if I changed the behavior of the database class so that it no longer returns null in this case, the business logic class will still function and the error will only be detected in QA unless someone remembers the connection, or the proper one Methods for using the method were observed.
I fell as if I had missed something, and there should be a better way to avoid this conceptual duplication, or at least try it out so that if it has changed, the fact that the change does not apply, w100>.
Any suggestions?
UPDATE:
Let me try to clarify my question. I think about when the code evolves over time, how to ensure that the integration does not interrupt between the classes tested with the layout and the actual implementation of the classified ones that mock represents.
For example, I just had a case when I had a method that was originally created and did not expect null values, so this was not a test on a real object. Then, the user of the class (checked using the layout) was strengthened to pass null as the value of the parameter under certain circumstances. About integration, which broke down because the real class was not tested for zero. Now, when you build these classes first, it doesn't really matter because you test both ends as you build, but if the design needs to develop two months later, when you tend to forget about the details, how would you test the interaction between these two sets of objects (one checked using layout versus actual implementation)?
The main problem, apparently, is duplication (which violates the DRY principle), expectations are really stored in two places, although the relationship is conceptual, and the actual duplicate code is missing.
[Edit after Aaron Digullah the second edited his answer]:
That's right, this is exactly what I am doing (except that there is some further interaction with the database in the class that is tested through DBUnit and interacts with the database during its tests, but this is the same idea), So now, let's say , we need to change the behavior of the database so that the results are different. The test using the layout will continue to pass if 1) someone does not remember, or 2) it breaks down in integration. Thus, the return values of the stored procedure (say) of the database are essentially duplicated in the test layout data. Now, what bothers me about duplication is that the logic is duplicated, and that is a minor DRY violation. Maybe it is so (there is a reason for integration tests in the end), but I felt that instead I was missing something.
[Change when starting the bonus]
Reading interactions with Aaron goes to the bottom of the question, but what I'm really looking for is some understanding of how to avoid or manage obvious duplication, so a change in the behavior of the real class will show in unit tests that interact with the layout as something that broke. Obviously, this does not happen automatically, but there may be a way to develop the script correctly.
[Change upon award]
Thanks to everyone who spent time answering the question. The winner taught me something new about how to think about transferring data between two layers, and received the answer first.