If method A's single role is to call method B, should I write a test that verifies method B is called when I call method A? Or is this a waste?
EDIT: I am editing to add some context. Here is my class:
module PaidGigs
class UserValue
def initialize(user)
#user = user
end
def default_bid(multiplier = 3.5)
PaidGigs::UserValue.cpm_value(#user.instagram_follower_count, multiplier)
end
def bid_value_including_markup(user_bid, multiplier = 3)
user_bid + PaidGigs::UserValue.cpm_value(#user.instagram_follower_count, multiplier, 0)
end
def self.cpm_value(base_count, multiplier, rounder = -1)
((base_count.to_f / 1000) * multiplier).round(rounder)
end
end
end
Should I write a test that verifies '#default_bid' calls '.cpm_value' with the proper arguments? Is this a waste of time, or is there value in this?
Don't test that one method within a method calls another. This will lead to a more fragile test, and create a barrier (although a small one) to refactoring. Your test should not care about the internals that produce the result, only that it's correct.
The answer changes if the method is delegating to another class - then you absolutely need to test, in a unit test, that the delegation occurs corectly by mocking the delegate.
There's value in methods that call others within the class: the name of the methods communicates the purpose of the method (if it's named well) and that's good for the human readers of your class. Well-named methods (and everything else) is hugely powerful, and largely underutilized. The names of low-level methods within a class can create a mini-DSL (Domain Specific Language) within the class, helping the reader to quickly understand what a high-level method is doing without taking the time to dig into the details.
What you're asking about is does it make sense to explicitly test everything your object does, or do you want to implicitly test it.
This is mostly a matter of opinion.
Personally, I see no value in writing that test, because eventually you should be writing a test that mocks out the return value of the method and verifying that function your testing actually mutates the mocked value in such a way. This way you implicitly test that you're calling the function - if you weren't using the method to get your end result, then the value would not align to your expected result.
Edit: A code example in something a bit more readable:
Calculator.cs
public class Calculator {
private IAddingService _addingService;
public Calculator(IAddingService addingService) {
_addingService = addingService;
}
public AddNumbers(int valueOne, int valueTwo) {
return _addingService(valueOne, valueTwo);
}
}
CalculatorTests.cs
public class CalculatorTests {
public void test_adding_numbers() {
var addingService = new Mock<IAddingService>()
addingService.Setup(service => service.Add(1,2)).Returns(2);
var calculator = new Calculator(addingService.Object);
var result = calculator.Add(1,2);
Assert.That(result, Is.EqualTo(2));
}
}
In this example, I've implicitly tested that adding service is the way that we add things because there's no action that allows calculator to determine this on its own.
I don't see why you wouldn't test it. It's easy to do and partially prevents further refactoring of this method to break something.
Related
I have this problem. I have a method in a class which gives me some return value. This method also makes changes to the state of the instance of that class. I need to unit test them both, so I made the test cases for the return value and copied them and just changed the assert from testing the return value to testing the change in representation (the only way for me to test this class is to test its representation). However, this does not seem like a very good way to deal with this. If I ever have changes in the functionality of the class, I will have to change the Act in the AAA in both test cases. How do I go about testing this? Is there some pattern to do that? Having both asserts in one test would mean I would be testing two things in one test case. In some languages (like JavaScript), I know I can make an array of tuples with the functionality, the assert for the return value and the assert for the representation, but I'm not sure a) how much better that is over some copy-pasting and b) what to do in other languages (e.g. in C# I imagine I'd have to make some classes with the asserts and include them in test cases).
Edit: For example:
class A {
state;
foo(animal, foodAmount) {
let returnResult = {};
//does things with animal and foodAmount
//which things change BOTH returnResult and the state variable
return returnResult;
}
bar() {
let stateToReturn = "";
//state is used to change the stateToReturn variable
return stateToReturn;
}
}
Here I will test function foo with a) an animal that does not exist currently, b) an animal that exists where I will add a non-zero amount of food to make sure the amount of food changes, c) two different animals to make sure they do not interfere with each other's food amounts, etc. I will do all these tests and make sure the returnResult variable is correct. The problem is that I need to make sure it does not only affect the returnResult variable, but also the state. The bar function is the only way for me to see the inner state. How would I go about testing the foo function? Would I write all tests twice (once to check foo returns the correct result and once to check foo changes the state correctly)?
Even with your example it's still a bit vague. The general and short answer to your question is: You should test for behavior, not methods. If that requires you to make assertions on the result of multiple methods in one test that's perfectly fine.
You shouldn't, however, expose the internal state of your class just to make it testable. It's better to test against the public api of your class. After all, that's how the production code interacts with it.
If a method changes the internal state but there is nothing in the public api that makes the change visible, how do you test it? You probably have a hidden concept in your class that should be extracted into its own class with its own public api. You can test the new class independently and the interaction between the two classes. This leads to smaller and more focused tests.
I'm not sure if this answers your question sufficiently but maybe there's some food for thought.
I have a quite complicated method for which I want to test the behavior (using Mockito and JUnit). This method takes an object (let's call its type State) as input, and should take a few different state variables into account for deciding its output.
As an example, considering the following specification (s is a mock of the State class):
If s.varOne is set, return its value.
Else, if s.varTwo is set, return that instead.
Else, if s.varThree is set, call s.update(s.varThree) and then return s.varOne, which will now have a value (even though it didn't at stage 1.)
Else, throw an error.
In order to test case 3 properly, I would like to set up the s object so that s.varOne and s.varTwo are both unset to begin with, but if (and only if!) the sut calls s.update(s.varThree), then after that s.varOne returns something.
Is there a good way to setup this behavior in Mockito?
I have considered setting up some chain of return values for s.varOne, and then verifying that the order of the calls corresponds to the order of the outputs (as well as that the return value of the sut is correct, of course), but this feels dirty; if I then change the method to calculate its return value in some other way, which calls s.varOne a different number of times but doesn't change its output, then the test will fail even though the functionality is the same.
My ideal solution is a way where I can add some "delayed" setup for the mock object, which is run when the sut calls the s.update() method, but I can't figure out a way to accomplish that.
You have a couple of options to mock a state change here, a good option and a better option. The best option, as tieTYT notes above, is to just to untangle the general contract of State: Does it really make sense for State to be mutable, and to have self-mutating methods that aren't simple setters?
The good option (sometimes) is to create a disposable subclass—or, better, an interface implementation—of State.
#Test public void yourTest() {
SystemUnderTest sut = createSystemUnderTest();
State state = new State() {
#Override public void update() {
this.varOne = 42;
}
}
// rest of your test
}
At that point, you may not need Mockito at all. Be warned, though: This can get a little tricky if State has side-effects or is otherwise difficult to instantiate. You could extract an interface, which would require you to wrap your fields in getters; you could also make State a named abstract class and then pass mock(MyAbstractState.class, CALLS_REAL_METHODS), but that gets particularly hairy when you consider that no initializer actually runs on that fake instance, and consequently the fields are all zero or null. If it's not simple, don't waste your time forcing a square peg into a round hole.
A more-common pattern for mocks is to use a custom Answer, in which you can execute arbitrary code at the expense of type safety. Here's an example, assuming update is void and varThree is an integer:
#Test public void yourTest() {
SystemUnderTest sut = createSystemUnderTest();
final State s = Mockito.mock(State.class);
doAnswer(new Answer<Void>() {
#Override public Void answer(InvocationOnMock invocation) {
int actualVarThree = (int) invocation.getArguments()[0];
assertEquals(EXPECTED_VAR_THREE, actualVarThree);
s.varOne = actualVarThree;
return null;
}
}).when(s).update(anyInt());
// rest of your test
}
Note that the array of arguments is an Object[], so the cast is necessary and slightly-dangerous, but then you can make all sorts of assertions and modifications synchronously when your mocked method is called.
Hope that helps!
I'm taking my first steps with unit testing and have a problem with encapsulation. My class has some private member variables that shouldn't be visible to the client, but in order for me to put object in a state I want to test it under, I need to set those private variables.
Say I have a code like that:
Class Foo {
public:
int action() ;
private:
int state ;
} ;
int Foo::action()
{
if(this->state == 1)
return 1 ;
else
return 0 ;
}
So now I want to test Foo::action(), but I need to be able to set Foo::state to be able to check function under different scenarios. One solution is the evil "define private public" in tests code. But is there something more elegant? I would like to stress that Foo::state is a variable that shouldn't be accessed by client, so I don't want to declare any public setter.
Edit:
I now think that extending the class I want to test in test code and including setters in that derived class would work, providing I changed private variables to protected. But that's a 'one generation only' solution and still feels like a hack rather than a proper approach.
Edit 2:
After reading answers and comments I was given (thanks to Lieven and ap. in particular) I believe the actual class I'm trying to test now (not the simple example I provided) simply does too much and the answer to my problem is moving some of its logic into another class that will be used by the big guy.
There are only two posibilities (refactoring asside)
Use the public interface to set the state.
The state is redundant if you can't set it to through the public interface.
Option 2 is self explanatory and most likely not applicable to your case so you are left with setting the state through the public interface of your class.
As you have already mentioned, this is possible but it requires a lot of code to get to the right state. That in itself could be an indication that your class is currently doing to much and it's time to refactor parts of your class into smaller, testable classes.
From Do not test private methods
If you find the need to test a private method, then you’re doing
something else wrong. There is an “upstream” problem, so to speak. You
have arrived at this problem due to some other mistake previous in
this process. Try to isolate what that is, exactly, and remove that
rather than bending your tests to go down a painful road of
brittleness in testing.
and Unit testing private members
I'd recommend not unit testing private methods. Since they're
private, they may be changed in any conceivable (or inconceivable?)
manner between each release. If a given private method is so critical
to the operation of the class that you feel it deserves test cases,
then it's probably time to refactor that out into a protected or
public method
A common quote on this is
You should never touch your privates
If your test class is called MyTestClass, then add MyTestClass as friend in class Foo to be able to access its private member variables.
Class Foo {
public:
int action();
private:
int state;
friend class MyTestClass;
};
You should be having some publicly (or "protectedly") accessible mechanism to change the value of the private variable state. For simplicity, let's say it is a method Foo::setState(int inState). Use that in the unit test to change the state, and thus test the Foo::action() method. This ensures that any future implementation changes would not affect the unit test (unless the "API" Foo::setState() changes - in which case, of course, you have to change the unit test).
If you do not have such a mechanism to change state, it means the end user or calling code cannot change it either, and hence, you wouldn't need to test it (and maybe that makes state redundant, but I don't know about that).
If the private variable changes "indirectly" through other code, you will have to execute the same code in the unit test. You can always trace back any method visible externally to inputs fed to the code externally. Basically the point is that in the unit test, you would have to feed the same inputs to the code as in the "real" scenario, and then test if it responds as it should.
As discussed in the comments below, if the "path" from the input to the code being tested is too long, the code/test may have to be broken into smaller modules or intermediate points. To elaborate, consider the code flow as:
Input -> A -> B -> C -> Output
// A, B, C are intermediate execution points which are not "publicly accessible".
In the above case, all you can do is
Given Input, check if Output is correct.
Instead, it would be good to expose the intermediate A, B, C, at least to the unit tests, so that you can now break your test into:
Given Input, check if A is correct.
Given A, check if B is correct.
Given B, check if C is correct.
Given C, check if Output is correct.
As you can imagine, if the test fails, it becomes easier to figure out what failed, and hence to fix it.
I have class file has a method like this:
public boolean validate(String str) {}
There're lots of codes inside this validate method, but I only want to make it always return true or false. Can someone point me out how to modify a class file to achieve this?
RULE override rtn
CLASS Foo
METHOD validate
IF true
DO RETURN true
ENDRULE
http://www.jboss.org/byteman
Are you trying to unit test this code and force an answer without caring about the conditions? If that is the case, then you are looking for "Mocking" frameworks. In Java, I can think of Mockito and EasyMock off of the top of my head.
Relatedly, you can use PowerMock (works in tandem with either of the above Mocking frameworks) to dynamically change classes (such as final classes/methods, static methods, and even private pieces of classes). PowerMock actually can change the byte code when necessary. Check under its classloading folders.
I've never considered it, but it might be possible to use any of them within non-test code, but they may require finagling to avoid JUnit dependencies (such as JUnit Runner). Again, I have never thought about it, so I never thought through the implications.
At the very least, you can probably look through PowerMockito to see how they change the byte code.
If you just want to unit test, then it's extremely easy and you probably don't need to worry about the byte code.
public class SomeClass {
public boolean validate(String s) {
// tons of logic
}
}
Test (using Mockito with JUnit 4 (drop the #Test attribute for JUnit 3)):
private final MyClassBeingTested testClass = new MyClassBeingTested();
#Test
public void testMyCodeWithSomeClass() {
SomeClass some = mock(SomeClass.class);
when(some.validate(anyString())).thenReturn(eq(true));
// whenever it uses "some.validate()", with any
// string, then it will return true
testClass.useSomeClass(some);
// assert whatever conditions you want
// if you care to ensure that it called validate:
// note: times(1) is implied if not supplied, but times(0), times(2), etc.
// could be used ("never()" exists as a synonym for times(0))
verify(some, times(1)).validate(anyString());
}
It can only return true or false, according to the method signature provided.
Can you make a wrapper class that delegates calls to the original and overrides the behaviour that you require, instead of trying to manipulate the bytecode?
The simplest way to modify the byte code is to decompile the class or get a copy of the source code. Change the code and compile it. Put the new version earlier in the classpath or replace the original in the jar. This way you have changed the method.
You can change it at runtime, but that is 100x harder. ;)
It seems as though the general consensus of the testing community is to not test private methods. Instead, you should test private methods by testing the public methods that invoke them. However, something just doesn't feel right to me. Let's take this method for example:
/**
* Returns the base name of the output generator class. If the class is named
* Reno_OutputGenerator_HTML, this would return "HTML".
*
* #return string
*/
protected function getName()
{
$class = get_class($this);
$matches = array();
if (preg_match('/^Reno_OutputGenerator_(.+)$', $class, $matches))
{
return $matches[1];
}
else
{
throw new Reno_OutputGenerator_Exception('Class name must follow the format of Reno_OutputGenerator_<name>.');
}
}
This particular function is used in a couple of places in my class. I'd like to test both branches of the if statement in this function, which would mean for each public function I'd have to test those 2 situations plus whatever else the public method itself does.
This is what feels weird for me. If I'm testing to see if getName() throws an Exception when a certain specific condition is met, then that means that I have to know implementation details of the private method. If I have to know that, then why shouldn't I just extend the class, make the method public, and test it that way?
(BTW: If you're wondering why such a weird method exists, this is used to automagically figure out what directory this class's template files are stored in).
The way I understand unit testing, this is exactly the kind of testing I would want to do. I have always looked at unit testing as white-box testing; if there's a branch point in my code, that means I need two unit tests to address it. I think the worst case I ever wound up with was a single method with 32 permutations.
The challenge with unit-testing is that if you don't explore all the edge cases by examining your code and figuring out all the different paths, you wind up missing one or more cases and possibly introducing subtle bugs into your application.
So, no, I don't see what you're proposing as weird. The method can stay internal, and you can add an extra test case - you probably only need the one with the exception, right?
Alternatively, you could refactor the functionality into a separate object that takes your generator object and returns its name (based on the algorithm above). That would justify separating the tests, because you'd have a name-extractor object, and the output generator implementations. I'm still not sure that this would save you a lot, because you'd still have to test the output generators to make sure they were using the name extractor correctly, but it would separate your functional and testing concerns.
You could also test this function by deriving from the class in your testclass like this:
namespace TheProject
{
public class ClassUnderTest
{
protected string GetName()
{
return "The name";
}
}
}
namespace TestProject
{
[TestClass]
public class TheTest:TheProject.ClassUnderTest
{
[TestMethod]
public void TestGetName()
{
string expected = "The name";
string actual = GetName();
Assert.AreEqual(expected, actual);
}
}
}
That way you keep your method private and you don't need to refactor your code to another class.