I have the following objects and relationships,
Lecture >- Tests
Test >- Questions
Business rules
When the lecture is started, a test can be given
If a test is being given, questions can be asked
Inference
Therefore questions shouldn't be asked if the lecture hasn't been started.
Question Model
class Question
belongs_to :test
belongs_to :lecture, :through => :test
def ask_question
raise "Test not started!" unless test.started?
raise "Lecture not started!" unless lecture.started?
end
end
So clearly the state of the question model is now coupled to the state of test and class.
When creating unit tests, to test this I need to set up all this state, which gets quite unwieldy, especially as the business cases get more and more complicated.
How can I avoid this?
I’m not experinced with Ruby associations, but it seems to me that somehow data model is cofused with run-time logic here.
If I’d make a data model for question and tests, I’d want to re-use my questions across tests and also re-use prepared tests (sets of questions) across lectures. In that case I’d write something like
Separately from that structure I’d have some structure corresponding to real-time lectures, tests, questions and a notion of a result. A result is an attempt to answer a real-time question by a given student.
I’d also “delegate” the check of the lecture session state to the test session. If test session cannot be started for whatever reason the question session cannot be started too.
To unit-test a question session you will only need to mock a test session, to unit test a test session you will need to mock a lecture session, and so on.
Hope this helps.