My goal is to be able to write unit tests for static methods that advocate:
Maintainability - I want the code to be as easy to follow, understand, and debug over time.
Performance - I'd like the speed of our tests not to suffer due to our technical debt if possible.
Constraints: We cannot refactor the static method to be an instance method. That would be first thing I would probably suggest, but I'm looking for an options/alternatives and opinions.
Testing static methods is a bit of a pain. There was a time that we could do this with phpunit. Mockery supports a means to test static methods through aliasing, but its not recommended. I've found that running these types of tests can be very slow. (hence the Goal #2).
Unfortunately, if you have a fair amount of code that relies on other code using static methods, you are at mercy of your own debt. There are some techniques using call_user_func(https://medium.com/#nihon_rafy/how-to-mock-static-methods-for-unit-tests-in-php-18b2a11458d0) and forward_static_call_array() (http://miljar.github.io/blog/2014/01/29/phpunit-testing-static-calls/), but I find myself having difficulty following this code.
I want to provide an alternative dynamic option, similar to the above.
class LegacyClass {
public static function staticMethod($a, $b, $c) {
return QueryBuilder::where($a, $b, $c)->getAll();
}
}
class ClassToTest {
public function test($a, $b, $c) {
return LegacyClass::staticMethod($a+1, $b+2, $c+3);
}
changes to this =>
class LegacyClass {
public static function staticMethod($a, $b, $c) {
return QueryBuilder::where($a, $b, $c)->getAll();
}
}
class ClassToTest{
// #var string fully qualified class name
private $legacyClass = LegacyClass::class;
public function test($a, $b, $c) {
return {$this->legacyClass}::staticMethod($a+1, $b+2, $c+3);
}
Now, with the above, we can mock the LegacyClass, get the class name of that mock, and use Reflection to set the private $legacyClass variable.
With that, my questions:
Which of the options above present the most maintainable solution?
Are there any better alternatives that meet the stated goals? (If so, I can append)
Thank you for your input!
A solution that I have been going back to very often is creating a "man-in-the-middle"-class. I use this for static function calls but also for cases where a new Object(); was created in the middle of the code.
In essence you are simply moving the problem somewhere else which might not look like a good solution but you make your ClassToTest easily testable by moving one line away.
So in short; I would make a new class (StaticFunctionCallerClass). This class would have one function that has one line.
class StaticFunctionCallerClass {
public function test($a, $b, $c) {
return LegacyClass::staticMethod($a+1, $b+2, $c+3);
}
Now you can instantiate this class in your ClassToTest (and therefore mock it in the test). So you can test all the logic around it and even test that your new StaticFunctionCallerClass is also called with the right information.
The drawback here is that it leaves your new StaticFunctionCallerClass with the line of hard to test code. You could call this class in your LegacyClassTest to test if the call is done correctly though, which is maybe not a very clean option but it does get the job done.
Related
I want to use Google test to test my class.
Lets assume I have a state machine implementation and the current state is private
so I have a method SetNextState that looks like that:
void setNextState
{
switch(m_currentState) //m_currentState is a private member
{
case INIT_STATE:
{
if some conditions occurred m_currentState=GO_STATE
}
......
}
}
so I have several cases and each define the behavior to move from certain state to another.
My question:
How do I perform tests on that method assuming the state is relevant only to this class so there is no output
How do I set its value to be, for example "GO_STATE" to test the GO_STATE case
and how do i check the m_currentState at the end of the test
Im trying to avoid putting friends etc. in my UUT code since I want it to be as original as possible
You don't. You do the same thing that your actual program will do, which is provide an input, then examine the result; you say there's no output, but there must be some effect, otherwise the class is pointless!
Failing that, you could make the test a "friend" of the class so that it can inspect its internals, or add an immutable getter for the current state (and who really cares if your class's users get to see that?) but neither option is really in the spirit of the thing.
In my experience, you'll occasionally realise that you're not really unit testing any more but instead functional testing, and Google Test may not be the right tool for that job. If your class is as big as it sounds, that could be the case here. Conversely, you could help yourself by splitting the class into smaller chunks, then unit testing those. Depends what you're going for, really.
Lightness Races in Orbit is correct. However, if sometimes you feel like it's useful to test the private member functions of your class, it often means that your class could be split in multiple smaller pieces.
If you don't think those smaller components are useful to the clients of your library, you can simply hide them in a detail:: namespace and then create unit tests as usual. This will allow you to test the internal behavior of your classes without polluting your public API.
After much considerations I decided to wrap my UUT with a helper which provides set and get to the relevant private members.and use it in the test procedure before calling the tested API
Original code
===============
class UUT //That's the actual class I want to test
{
protected:
int m_protectedMember;
public:
void methodToTest()
{
//Do something with m_protectedMember use its value as input
//and set it as output
}
};
In the tester
==============
class UUTHelper: public UUT
{
public:
int getProtectedMember() { return m_protectedMember; }
void setProtectedMember(int value) { m_protectedMember = value; }
};
The pros:
My test code is very simple and I easily create complicated scenarios .
I test the real code without any "friends" or any other manipulations.
The cons:
As written in the discussion, not the best "good practice", touching private members
Thank you all :)
Suppose the following template method implementation:
public abstract class Abs
{
void DoYourThing()
{
log.Info("Starting");
try
{
DoYourThingInternal();
log.Info("All done");
}
catch (MyException ex)
{
log.Error("Something went wrong here!");
throw;
}
}
protected abstract void DoYourThingInternal();
}
Now, there are plenty of info around on how to test the Abs class, and make sure that DoYourThingInternal is called.
However, suppose I want to test my Conc class:
public class Conc : Abs
{
protected override void DoYourThingInternal()
{
// Lots of awesome stuff here!
}
}
I wouldn't want to do conc.DoYourThing(), since this will invoke the parent method, which was already tested separately.
I would like to test only the overriding method.
Any ideas?
You have labeled the question "tdd" but I doubt you've followed that principle when you encountered this "problem".
If you truly followed tdd your work flow would have been something like
Write a test for some logic not yet implemented
Impl the easiest possible impl for this test to make it green (logic on Conc1 for example)
Refactor
Write a test for some other logic not yet implemented
Impl the easiest possible impl for this test to make it green (logic on Conc2 for example)
Refactor
In "6" you might think that it would be a great idea to implement a template method because Conc1 and Conc2 share some logic. Just do it, and run your tests to see that the logic still works.
Write tests to verify the logic, don't base them how the implementation look like (=start with the tests). In this case, start writing tests verifying that the logic works (the logic later placed in your concrete types). Yes, that means that some code lines (the one in your abstract class) are tested multiple times. But so what? One of the point of writing tests is that you should be able to refactor your code but still be able to verify that it works by running your tests. If you later don't want to use template method pattern, in a ideal world your shouldn't need to change any tests, but just change the implementation.
If you start to think which code lines you test, IMO you loose much of the benefits of writing tests at all. You want to ensure that your logic works - write tests for this instead.
I assume part of the 'problem' is that there is no way to call a protected method from outside the class. How about a mock class which derives from Conc and provides a new public method:
public class MockConc: Conc
{
void MockYourThingInternal()
{
DoYourThingInternal()
}
}
I wouldn't consider DoYourThingInternal() to be separate from DoYourThing() (as in, two separate modules of code that can be tested in isolation) since you won't be able to instantiate your abstract class alone anyways and the 2 methods will always be run together. Besides, DoYourThingInternal() has access to all protected members of your class and could modify them, with potential side effects on DoYourThing(). So I think it would be dangerous to test DoYourThing() in complete isolation from a concrete implementation of DoYourThingInternal().
However, that doesn't mean you can't have separate tests for DoYourThing()'s expected behavior, which has to remain the same across all implementations of Abs, and DoYourThingInternal()'s expected behavior.
You could use an (abstract) base test class where you define a test for the general behavior expected from DoYourThing(). Then create as many test subclasses as there are implementations of Abs, with unit tests for the specifics of each implementation.
The test from the base test class will be inherited, and when you run any subclass's tests, the inherited test for DoYourThing() will also run :
public abstract class AbsBaseTest
{
public abstract Abs GetAbs();
[Test]
public void TestSharedBehavior()
{
getAbs().DoYourThing();
// Test shared behavior here...
}
}
[TestFixture]
public class AbsImplTest : AbsBaseTest
{
public override Abs GetAbs()
{
return new AbsImpl();
}
[Test]
public void TestParticularBehavior()
{
getAbs().DoYourThing();
// Test specific behavior here
}
}
See http://hotgazpacho.org/2010/09/testing-pattern-factory-method-on-base-test-class/
Don't know if abstract test class inheritance is supported by all unit test frameworks though (I think NUnit does).
What about sticking an interface on Abs and mocking it? Ignoring the calls, or set expectations on them?
You could do it several ways, many of which are documented here already. Here is the approach I typically take: Have the test case inherit from the concrete class.
public ConcTest : Conc
{
[Test]
public void DoesItsThingRight()
{
var Result = DoItsThingInternal();
// Assert the response
}
}
Hope that helps!
Brandon
I'm writing program arguments parser, just to get better in TDD, and I stuck with the following problem. Say I have my parser defined as follows:
class ArgumentsParser {
public ArgumentsParser(ArgumentsConfiguration configuration) {
this.configuration = configuration;
}
public void parse(String[] programArguments) {
// all the stuff for parsing
}
}
and I imagine to have ArgumentsConfiguration implementation like:
class ArgumentsConfiguration {
private Map<String, Class> map = new HashMap<String, Class>();
public void addArgument(String argName, Class valueClass) {
map.add(argName, valueClass);
}
// get configured arguments methods etc.
}
This is my current stage. For now in test I use:
#Test
public void shouldResultWithOneAvailableArgument() {
ArgumentsConfiguration config = prepareSampleConfiguration();
config.addArgument("mode", Integer.class);
ArgumentsParser parser = new ArgumentsParser(configuration);
parser.parse();
// ....
}
My question is if such way is correct? I mean, is it ok to use real ArgumentsConfiguration in tests? Or should I mock it out? Default (current) implementation is quite simple (just wrapped Map), but I imagine it can be more complicated like fetching configuration from kind of datasource. Then it'd be natural to mock such "expensive" behaviour. But what is preferred way here?
EDIT:
Maybe more clearly: should I mock ArgumentsConfiguration even without writing any implementation (just define its public methods), use mock for testing and deal with real implementation(s) later, or should I use the simplest one in tests, and let them cover this implementation indirectly. But if so, what about testing another Configuration implementation provided later?
Then it'd be natural to mock such "expensive" behaviour.
That's not the point. You're not mocking complex classes.
You're mocking to isolate classes completely.
Complete isolation assures that the tests demonstrate that classes follow their interface and don't have hidden implementation quirks.
Also, complete isolation makes debugging a failed test much, much easier. It's either the test, the class under test or the mocked objects. Ideally, the test and mocks are so simple they don't need any debugging, leaving just the class under test.
The correct answer is that you should mock anything that you're not trying to test directly (e.g.: any dependencies that the object under test has that do not pertain directly to the specific test case).
In this case, because your ArgumentsConfiguration is so simple, I'd recommend using the real implementation until your requirements demand something more complicated. There doesn't seem to be any logic in your ArgumentsConfiguration class, so it's safe to use the real object. If the time comes where the configuration is more complicated, then an approach you should probably take would be not to create a configuration that talks to some data source, but instead generate the ArgumentsConfiguration object from that datasource. Then you could have a test that makes sure it generates the configuration properly from the datasource and you don't need unnecessary abstractions.
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.
I'm trying to run the following code with Ninject.Moq:
[TestMethod]
public void TestMethod1()
{
var kernel = new MockingKernel();
var engine = kernel.Get<ABC>();
//as I don't need to actually use the interfaces, I don't want
//to even have to bother about them.
Assert.AreEqual<string>("abc", engine.ToString());
}
And here is the ABC class definition:
public class ABC {
IA a;
IB b;
public ABC(IA a, IB b)
{
this.a = board;
this.b = war;
}
public override string ToString()
{
return "abc";
}
}
I'm getting the following exception:
System.ArgumentException: A matching
constructor for the given arguments
was not found on the mocked type. --->
System.MissingMethodException:
Constructor on type
'AbcProxya759aacd0ed049f3849aaa75e2a7bade'
not found.
Ok, this will make the code work:
[TestMethod]
public void TestMethod1()
{
var kernel = new MockingKernel();
kernel.Bind<Abc>().ToSelf();
var engine = kernel.Get<ABC>();
//as I don't need to actually use the interfaces, I don't want
//to even have to bother about them.
Assert.AreEqual<string>("abc", engine.ToString());
}
One has to bind Abc to itself, otherwise it will also get mocked and Moq only supports mocking parameterless classes, which is not the case.
It's a bit like understanding DI in the first
place :- small samples don't really get the whole point across.
An automocking container like Ninject.Moq (or similar test infrastructure libraries like AutoFixture) is hard to really explain with a simple example. I'd suggest reading all of Mark Seemann's posts on AutoFixture as a way of getting a feel fro the requirement.
So Ninject.Moq will deal with the chaining, N levels deep of a set of stub implementations of interfaces that are necessary to satisfy your System Under Test in the course of doing the thing your test is actually supposed to be testing.
In general, you want short easy to read, easy to grok tests with minimal complexity and interaction of fixtures under the cover (no big hierarchy of base classes, or 6 different magic methods doing wacky teardown and calling base classes). Normally this aim will mean you should keep your DI toolery miles away from your unit tests.
An automocking container should, like a chainsaw, only be used where you're going to get a signnificant real return (many shorter, easier to understand tests) for you investment (another tool to understand before others can read you tests, more debugging, more surprises, more complexity that'll lead to brittle, unmaintainable tests).