Rails / Rspec - specification record for the delegate method (allow_nil option)

Based on the code below:

(1) How are you going to write a specification to test the option: allow_nil => false?

(2) Is it even worth writing a specification for testing?

class Event < ActiveRecord::Base belongs_to :league delegate :name, :to => :league, :prefix => true, :allow_nil => false end describe Event do context 'when delegating methods to league object' do it { should respond_to(:league_name) } end end 

Actually, it would be nice if you could continue working:

 it { should delegate(:name).to(:league).with_options(:prefix => true, :allow_nil => false) } 
+6
source share
2 answers

According to the documentation for the delegate rails module:

If the delegate object is zero, an exception is thrown, and this happens regardless of whether nil corresponds to the delegated method. You can get zero instead of the option: allow_nil.

I would create an Event event object using nil league or set event.league = nil , then try to call event.name and check that it throws an exception, as this is what should happen when allow_nil is false (this is also the value by default). I know rspec has this idiom for testing exceptions:

 lambda{dangerous_operation}.should raise_exception(optional_exception_class) 

Iโ€™m not sure if this construction will be available, although there are some articles, seemingly old, on how to get this behavior for purposes .

I think it is worth checking if this is the behavior that users of this class can expect or assume that it will probably be true in this case. I would not decrypt shoulda to check for โ€œmust delegateโ€, because it seems more dependent on the implementation: you really say that your event should throw an exception if you try to call #name when it has a nile league. It really doesn't matter to Event users how you do it. I would even go this far if you want to state this and notice this behavior to verify that Event#name has the same semantics as League#name , without mentioning anything about delegate , as it is a behavior-oriented approach .

Build your tests based on how your code works and not how it is built - thus checking this document is the best documentation for those who stumble on your tests, as they are more interested in the question โ€œwhy does my event throw ? " or "what could trigger the event?" than "is this the delegation of this event?"

You can highlight this situation by imagining what kind of setbacks can happen if you change your code so that users of the event are not interested. If they are not interested, the test should not be interrupted when you change it. What if, for example, you want to process the delegation yourself by writing the #name function, which first registers or increments the counter, and then delegates it to league ? by testing the behavior that throws an exception, you are protected from this change, but by checking if the Event is a delegate, you will break this test when you make this change - and therefore your test did not look at what is really important in relation call #name .

In any case, all the talk about soap bubbles. tl; dr: check this out if this behavior can rely on someone. All that has not been tested is the Shroedinger cat: broken and not broken at the same time. In truth, most of the time it can be OK. It is a matter of taste, do you want to say something strict and final about how the system should behave, or just let it be "unspecified behavior".

+9
source

So, a couple of things here about whether to test this:

1) I do not think that there is something wrong to understand this behavior. If you have users who need to study your software / library, this is often very useful to ensure that all of your methods that are part of your public contract are specified. If you do not want to do this part of this api model, I would recommend doing delegation manually so as not to expose more methods to the outside world than you need.

2) Specifications of this kind help to ensure that the contract that you have with the object delegating delegation remains in force. This is especially useful if you use stubs and layouts in your tests, as they often execute the same contract, so at least you know when that contract changes.

In terms of how you test the allow_nil part, I agree with Matt, the best idea is to ensure that the league is zero and then try to name the league. This can be checked to ensure that nil is returned.

Hope this helps.

+2
source

Source: https://habr.com/ru/post/907539/


All Articles