Unit Testing and Checking Private Variable Value

Unit testing and checking private variable value

The quick answer is that you should never, ever access non-public members from your unit tests. It totally defies the purpose of having a test suite, since it locks you into internal implementation details that you may not want to keep that way.

The longer answer relates to what to do then? In this case, it is important to understand why the implementation is as it is (this is why TDD is so powerful, because we use the tests to specify the expected behavior, but I get the feeling that you are not using TDD).

In your case, the first question that comes to mind is: "Why are the IAuditable objects added to the internal list?" or, put differently, "What is the expected externally visible outcome of this implementation?" Depending on the answer to those questions, that's what you need to test.

If you add the IAuditable objects to your internal list because you later want to write them to an audit log (just a wild guess), then invoke the method that writes the log and verify that the expected data was written.

If you add the IAuditable object to your internal list because you want to amass evidence against some kind of later Constraint, then try to test that.

If you added the code for no measurable reason, then delete it again :)

The important part is that it is very beneficial to test behavior instead of implementation. It is also a more robust and maintainable form of testing.

Don't be afraid to modify your System Under Test (SUT) to be more testable. As long as your additions make sense in your domain and follow object-oriented best practices, there are no problems - you would just be following the Open/Closed Principle.

Angular (8) - Unit testing service with private variables

I agree that you should not access the private variables in your tests. If you do, your test will be useless when you need to do some refactoring.

I don't see an issue with calling the method twice in your tests. I am assuming it will happen in actual code since you are implementing a caching mechanism. "The more your tests resemble the way your software is used, the more confidence they can give you."

How to unit test if a private variable has changed

Short answer: Dont do it.

Your test should test against the public interface only. Let me try to explain with some code:

class Adder {
int a,b;
public:
Adder() : a(0),b(0) {}
void set(int x,int y) { a=x;b=y; }
int get() { return a+b; }
};

and a test (assume for a moment we had access to a and b):

void testAdder(){
Adder add;
int a = 1;
int b = 2;
add.set(a,b);
ASSERT_EQUALS(add.a,a);
ASSERT_EQUALS(add.b,b);
ASSERT_EQUALS(add.get(),a+b);
}

Suppose you already distributed the code and someone is using it. He would like to continue using it but complains about too much memory consumption. It is straightforward to fix this issue while keeping the same public interface:

class Adder {
int c;
public:
Adder() : c(0) {}
void set(int x,int y) { c = x+y; }
int get() { return c; }
};

That was easy, but the test will fail :(

Conclusion: Testing private implementation details defeats the purpose of testing, because each time you modify the code it is likely that you also have to "fix" the test.

How to unit test a private variable?

  1. No.
  2. You don't. You would be coupling your test to your implementation. If you were to refactor your implementation, you would want to have the confidence that if your test keeps working without having to modify it, you didn't break anything.

Think about what will go wrong (i.e. which part of the contract will be violated) if those variables are not correctly updated. Write a test for that, prove that it fails when it should, then make sure it doesn't fail.

How do I setup a private variable in a unit test

First of all, this method won't compile:

public void GetAllBs(DateTime time)
{
return _list;
}

It has return type void (returns nothing) but you return List<B>. Also, you don't need parameter to return result. Change it to:

public List<B> GetAllBs()

About testing: you can easily test your list. Your test method will be like this:

[TestMethod]
public void Test()
{
A a = new A();
a.AddNewB(DateTime.Now);
a.AddNewB(DateTime.Now);

Assert.AreEqual(2, a.GetAllBs().Count);
}

You should create object of class A and call AddNewB() to add some element. To be sure that list is not cleared after adding new element you should add one more and check Count of elements in the list. To do this you should call GetAllBs() - it will return list - and get Count. The Count should be equal to 2.

If you want to be sure that method is tested you can use some tool that shows code coverage(DotCover, OpenCover).

JUnit Testing private variables?

Yeah you can use reflections to access private variables. Altough not a good idea.

Check this out:

http://en.wikibooks.org/wiki/Java_Programming/Reflection/Accessing_Private_Features_with_Reflection

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.



Related Topics



Leave a reply



Submit