How to Set Private Instance Variable Used Within a Method Test

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



Leave a reply



Submit