How to set private instance variable used within a method test?
As you answered in your question the easiest way to set instance variable is with instance_eval
method:
obj.instance_eval('@a = 1')
Another way is to use instance_variable_set:
obj.instance_variable_set(:@a, 1)
But I would not recommend to do this in your specs. Specs are all about testing behavior of an object and testing behaviour by breaking class encapsulation with instance_eval
will make your tests more fragile and implementation dependent.
Alternative approach to object state isolation is to stub accessor methods:
class UnderTest
attr_accessor :a
def test_this
do_something if a == 1
end
end
#in your test
under_test = UnderTest.new
under_test.stub(:a).and_return(1)
Is there any way to use an instance variable in another method?
For sharing logic/variables between @Test
methods, you can either use an instance method annotated with @Before
, which will be invoked once before every @Test
method, or a static method annotated with @BeforeClass
, which will be invoked only once for the entire test class before any @Test
methods run.
In your scenario, assuming you need to generate the mainId
value once and reuse the same value across multiple @Test
methods, you would need to use @BeforeClass
and store the value as a static variable, like so:
private static String mainId;
@BeforeClass
public static void init() { //must be public static void
String numeric = randomNumeric();
mainId = "D1234" + numeric;
}
@Test
public void somethingA() {
//use mainId (note that it belongs to class, not this instance)
//...
}
//other tests...
Note that changing mainId
and the doSomething
logic to be static requires you to change the randomNumeric
method to be static as well.
Rspec private method can't access class instance variable?
Your example is a bit confusing due to the various spelling errors in your attempt to generalize your problem. I created the following two files, and the specs ran just fine. Might be a naming error that you're experiencing and not an actual rspec problem.
# test_spec.rb
require 'rspec'
require_relative 'my_class'
describe MyClass do
describe '#initialize' do
let(:configs) { {some_token: '123-FakeToken'} }
let(:loader) { described_class.new(configs) }
context 'when initialized with a set of configs' do
it { expect(loader.instance_variable_get(:@configs)).to eq(configs)}
end
end
end
and
# my_class.rb
class MyClass
#@configs = {}
def initialize(configs)
@configs = configs
check_configs
end
private
def check_configs
if @configs[:some_token].nil?
puts "log message"
raise 'an error'
end
end
end
That said, the bigger question is what are you trying to accomplish with your tests?
Testing private variables is a smell. Ideally, in the case of config variables, they will cause an effect in your instance when set. For example MyClass.foo
will behave differently based on whether some_token
is set or not. Testing whether the behaviour of foo
changes with a some_token
present or not is a high value test that you want. Instead of a low value test of whether you wrote @configs = configs
correctly.
Is it possible to call an instance variable inside of a private function in javascript?
You simply have to specify the value of this
when calling your private method using Function.prototype.call
.
myPrivateMethod.call(this);
E.g.
function myClass(){
this.myPublicMethod = function(a,b){
var i = a*b;
return i;
}
function myPrivateMethod(){
var n = this.myPublicMethod(2,3);
}
//calling private method in the *scope* of *this*.
myPrivateMethod.call(this);
}
Please note that having true private members (that aren't functions) comes at the cost of not taking advantages of prototypes. For that reason, I prefer to rely on naming conventions or documentation to identify private members rather than enforcing true privacy. That holds only for non-singleton objects.
The following example demonstrates what is being said above.
//Constructors starts by an upper-case letter by convention
var MyClass = (function () {
function MyClass(x) {
this._x = x; //private by convention
}
/*We can enforce true privacy for methods since they can be shared
among all instances. However note that you could also use the same _convention
and put it on the prototype. Remember that private members can only be
tested through a public method and that it cannot be overriden.*/
function myPrivateMethod() {
this.myPublicMethod1();
}
MyClass.prototype = {
constructor: MyClass,
myPublicMethod1: function () {
//do something with this._x
},
myPublicMethod2: function () {
/*Call the private method by specifying the *this* value.
If we do not, *this* will be the *global object* when it will execute.*/
myPrivateMethod.call(this);
}
};
return MyClass;
})();
Is there a way to test an instance variable in objective c?
You can add setter only for testing in your test file myViewControllerTest.mm
This has no effect to your production code.
like below using Extension
// Write this in test file.
@interface MyViewController(Test)
- (void)setMyView:(NSView *)myView;
@end
or just use valueForKey:
to get private field.
-(void) myTest
{
id myViewController = ...;
NSView *myView = [myViewController valueForKey:@"myView"];
myView.window = nil;
// ...
}
Testing private variables - always bad practice?
The state of private fields is irrelevant to the correct functioning of the class. You shouldn't be testing private variables.
Test what the class does, not how it does it.
If you want to test that the class sets its internal state correctly, so it behaves in a particular way after that, then call the methods that set the state and test that the behaviour after that is correct.
It doesn't matter if it takes 1000's of tests to ensure that - they are only unit tests, so they'll be fast.
Future coders are at liberty to change the internal workings of a class, as long as the class' contract is upheld.
Modifying private instance variables in Java
See (my favorite table) Controlling Access to Members of a Class:
Modifier Class Package Subclass World
-------------------------------------------
public Y Y Y Y
protected Y Y Y N
no modifier Y Y N N
private Y N N N
↑
You are here
Since you're in the same class, private
members are available.
As mentioned in the comments, note that you're not overriding the correct equals
method. The original one (of Object
class), expects an object of type Object
as an argument.
How to make a real private instance variable?
You can use the @private
keyword inside the {}
to make all subsequent variable declarations private. The default visibility is @protected
(which is similar to protected
in Java) and that generally works well. You'd have to specifically declare a variable as @public
for it to be directly accessible outside the class.
This Apple documentation has further details about variable scope and visibility.
There is also a difference between "private API" and private variables. In Objective-C, you cannot make methods private — anyone can call any method. There are several ways to create "secret" methods, but that's somewhat out of the scope of this question. Here are a few related SO questions:
- About private instance variables in Objective-C
- What does “@private” mean in Objective-C?
- Is it possible to declare a method as private in Objective-C?
- Best way to define private methods for a class in Objective-C
As far as the leading _ in front of variables, be aware that Apple also reserves this prefix for "private" methods. The best way to guarantee you avoid problems is to use normal naming conventions for your own variables and methods. However, unless you subclass something from Cocoa (other than NSObject) you can be fairly confident that you won't run into problems.
Related Topics
What Does "Shadowing" Mean in Ruby
How to Convert a Ruby Object to JSON
How to Change Column Type in Heroku
Ruby Minitest: Suite- or Class- Level Setup
Dry Way to Assign Hash Values to an Object
Using $ Sudo Bundle Exec ... Raises 'Bundle: Command Not Found' Error
Reflection on Method Parameters in Ruby
Determining If a Variable Is Within Range
Rails 3.1 Absolute Url to an Image
Before/After Suite When Using Ruby Minitest
Convert String into Array in Rails
How to Fire Raw Mongodb Queries Directly in Ruby
What Does ::Myclass Ruby Scope Operator Do
Ruby Difference in Array Including Duplicates