I have some code in +initialize method of a class that I'd like to test (using simple OCUnit). Namely it's application delegate that sets some user defaults, so my testing would look like this:
Check for absence of values-to-be-set;
Load a class;
Check for presence and correctness of set values;
Do you have any hints on how can I achieve this?
Yup - You can move your defaults initialization implementation out to a separate function, which you call from +[MONObject initialize].
Test the function in a lower level suite which does not load the objc class (MONObject) into the objc runtime.
Then you can test it and destroy it in a separate executable, and rely on that proof in your app level test suite.
When you set "user defaults" defaults it is only used when no other value has been stored in the "user defaults". So, if you call a value from "user defaults" you get the default value unless you have stored value in a previous run (note you have to delete the App on the device because "user defaults" are stored between runs).
You should set defaults for all "user defaults", because it only applies when used for the first time.
I may have misunderstood what you are asking but I think that you are mixing set values in the default and default values that are used when none have ever been set.
I am also confused why you are loading a class in +initialize class method, that gets called before any instance is created?
Related
Although more of a Delphi language question, will use a specific example to try and get the idea across better:
using Delphi's TWebModule for an HTTP server, we can define endpoints as actions, and assign those actions an OnAction event, to execute code when a request is made to this given endpoint.
many, if not most of those actions require authorization: that is, they all start with the same block of code that checks for valid credentials and decides whether to allow the request to execute or not. So I started looking at how one could "group" a set of similar actions into maybe a subclass of the default action class (TWebActionItem) that adds authorization-specific code. One might also want to execute some generic before/after methods.
pseudo-code would look something like this, where TAuthWebActionItem is a subclass of TWebActionItem adding authorization code, and before/after method calls:
function TAuthWebActionItem.OnAction
begin
FBeforeAction // execute some initialization code
if authorized then // auth ok?
inherited // proceed
else
'you are not authorized'
FAfterAction // execute some finalization code
end
we would then create a TAuthWebActionItem, add it to the TWebModule's list of actions, and we're done.
however, the TWebModule and TWebActionItem classes do not offer virtual methods for overriding. Using "reintroduce" instead of "override" would not solve it either, as the TWebModule's actions list items are still of type TWebActionItem: calling the OnAction of a superclass, even if reintroduced, will not execute the subclass' code.
How would one bypass such limitations / constraints in the classes being used, to achieve what's outlined in the pseudo-code above?
In our company, repository objects must be created with original language EN.
Is there a way to check the logon language in case of creating a new object in the ABAP repository?
Desired behaviour:
SE80 - Create program/class/data element/table/....
==> user exit/badi checks the logon language. When it is not 'EN', the creation will be refused.
regards,
Umar Abdullah
I know there is a exit for this but I haven't remember exact name. You can use general purpose for finding exit. Go to SE24 and open CL_EXITHANDLER class, find GET_INSTANCE method and add break point. Then start creating item, it will pause on debugger multiple times, try to find suitable one.
As #mkysoft suggested, you may implement a check in the BAdI CTS_REQUEST_CHECK, method CHECK_BEFORE_ADD_OBJECTS, which is invoked when the object is about to be attached to a transport request. Raise the exception CANCEL to make the attachment fail (and so the object is not created too).
EDIT: sorry, ignore my answer, "this method is NOT released for Customer usage" as said in note 2150125 - Method CHECK_BEFORE_ADD_OBJECTS not triggered
DISCLAIMER: THE METHOD DESCRIBED HERE IS ABSOLUTELY NOT RECOMMENDED.
As correctly pointed out by the other members there is no standard and customer-exposed method to achieve your requirement, but if you absolutely must enable this check during creation you can use the below method. As well as the previously offered to you, it also involves modification of SAP standard.
There is a system BAdi CTS_TADIR_SUBSCREEN that is located inside enhancement point CTS_ES_TADIR_POPUP. They are SAP internal and not released for customer usage, so do this at your own risk.
Implementation procedure:
Step 0. First thing you need to change is a SAP internal usage flag, for which you need Object Access key which can be obtained from SAP or from SAP partner that made the implementation in your org. In virgin state this BAdi throws the error if you try to implement it
So hereinafter we assume that you already ticked off this checkbox in BAdi settings
Step 1.
In order to implement the BAdi one need to implement enhancement spot prior to that. This is the most complicated part, because despite we disabled internality flag the SAP-namespaced enhancements must be stored only in SAP-namespaced objects. By SAP namespace I mean non-Z, non-Y and non-T (Test). This means to implement this enhancement, besides modifying the enhancement definition, one need to create, for example, CTS_ES_TADIR named enh.impl., and save it to non-Z package, which you also need to create. Your enhancement implementations selector should look somehow like this
On the above screen only the second will work, all the rest Z will not.
Every non-Z object need Object Access Key, remember? Too bad. But just to show the proof-of-concept, I will proceed.
Step 2. After you created the enh. implementation in SAP-namespace it will propose you to create the BAdi implementation. The same principle applies here: only SAP-namespaced container for SAP-namespaced objects, hence CTS_TADIR_SUBSCREEN should have implementing class for example CL_TADIR_SUBSCREEN. During the creation of enhancement you will see many warnings
but finally you should have something like this, where all system-named objects are created and the enhancement/BAdi is activated.
Step 3. In order to get the BAdi working we need to enable this subscreen processing
during the playing with enhancement I found out that BAdi class is not being triggered standalone, without screen events not enhanced, so to make it work you need to touch a screen enhancement for screen 100
If you do not wanna modify screen elements logic, just put the dummy enhancement in SHOW_TADIR dialog module in the end of the include LSTRDO18
PROCESS BEFORE OUTPUT.
MODULE SHOW_TADIR. "<-- create the dummy enhancement here
CALL SUBSCREEN subs_info INCLUDING gv_badi_prog gv_badi_dynnr.
for example declaration statement like I did
Step 4. Activate your created BAdi class and put the necessary logic there. I wasn't able to trigger method GET_DATA_FROM_SCREEN, but PUT_DATA_TO_SCREEN worked fine
If we put this simple processing for your requirement
METHOD cts_if_tadir_subscreen~get_data_from_screen.
IF object_data-l_mstlang <> 'E'.
MESSAGE 'Objects in non-English languages are not allowed!' TYPE 'A'.
ENDIF.
ENDMETHOD.
it will not allow creating objects in languages other than English.
The check in method get_data_from_screen is being done before showing the screen so language is determined from system logon settings. If to play more with this BAdi, I suppose the method GET_DATA_FROM_SCREEN can also be enabled, which will make it possible to check user input, i.e. the case when the user gonna change the default language.
I am new to mocking and stubbing, but I think I have a circumstance where their use would be ideal.
In my application, when a user saves a Product, an after_save callback fires that creates Publication instances which cause the product data to be sent to certain 3rd parties via API.
I have a request spec for Product that tests my CRUD operations.
If I stub either the API methods or mock the Publication model, will those mocks/stubs be used in my spec even though they are actually called in the Product after_save callback? I'm confused about this point.
Update
I figured I would just do it like this:
Publication.any_instance.stub(:publist).and_return(true)
And do that at the beginning of my test. That way whatever instance is created would be handled. Is that how it works?
Yes that stub will do what it says and the publist method on any instance of the publication class will always return true.
Instead of putting it "at the top" though do something like.
context 'when there is a publist' do
Publication.any_instance.stub(:publist).and_return(true)
it 'should ...' do
...
end
end
then if required you can do tests without the stub, or tests where publist returns false in other context blocks and be nice and clear in the spec.
We’re using Ninject.Extensions.Interception (LinFu if it matters) to do a few things and I want to know if its possible to return a value form the method being intercepted.
EG
A Call is made into one of our repository methods
Our Interceptor gets the BeforeInvoke event, we use this to look into the ASP.NET Cache to see if there is any relevant data
- Return the relevant data (this would cause the method to return immediately and NOT execute the body of the method
- Or Allow the method to run as per normal
Extra points if in the AfterInvoke method we take a peek at the data being returned and add it to the cache.
Has anybody done something similar before?
From your question I assume that you derive from SimpleInterceptor. This will not allow to return imediately. Instead you have to implement the Iinterceptor interface. You can decide to call the intercepted method by calling the Proceed method on the invocation or not.
How would I test the following code?
Public Sub SetSerialIdForDevice()
Try
Dim component As Object = container.getComponentRef("componentInterface")
If component IsNot Nothing Then
component.SetupDeviceSerialID(container.serialNumbers)
Else
serialfound = False
End If
Catch ex As Exception
'' error handling
End Try
End Sub
Project references (or components as they're called here) are loaded at runtime into a singleton 'container.' We call the component that interfaces with a device by using the container.getComponentRef("< name of component we're looking for >"). We then invoke a method on this component to set the serial id, which is stored in a property of the container object.
In the SetupDeviceSerialID() method we call properties native to the 'container' (such as if it's an internal debug mode) as well as some other objects. What would be the best way to test this scenario where we have objects within objects? Would we mock all the calls, properties, and objects in order to isolate the test for SetupDeviceSerialID()?
Or do we mock the 'componentInterface' that's returned and mock the call for SetupDeviceSerialID() and then test the properties that were changed within SetupDeviceSerialID()?
EDIT
I've been thinking about testing this incorrectly (obviously) and through the answers I've come to realize that I was trying to cram testing for methods executed deeper in the code, into tests for the SetSerialIdForDevice() method.
So as a result,
If a serialID is found, we would set serialfound = true inside of SetupDeviceSerialID().
Is that something we would test here (since we will be testing for serialfound=false), or in a test for SetupdDeviceSerialID()? And would we create a test to see if SetupDeviceSerialID() actually exists on the "componentInterface" component?
I would mock container to have the getComponentRef return a mock object which the method can test against. Mocking each "componentInterface" class needs to be something that happens in their own dedicated unit tests. Don't combine testing responsibilities because its convenient, keep everything as its own unit so no unit test is dependent on another test.
The mores Seams you can put into your code, the easier it becomes to test.
If you can replace the return value of the getComponentRef method with a Test Double, you can write one test that verifies that this method has been invoked correctly and then move on to writing other unit tests that verifies something else.
Ideally, you should only be writing one test that tests any particular piece of behavior.
Assuming you can replace the component variable with a Test Double, you could then verify that the SetupDeviceSerialID method is called correctly.
That, as well as some tets that exercise the error paths, should then conclude the test suite for the SetSerialIdForDevice method.
You can then move on to write a new set of tests that verifies that a particular 'component' implementation works as intended, but those would be separate tests that are independent of the tests that exercise the SetSerialIdForDevice method.