Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit testing dependent methods

I would like to unit test a method on a class I have made, but this method requires another method to be called first. Example:

// This would work
MyClass myClass1 = new MyClass(mockDevice);
myClass1.Run(myDatastructure);
myClass1.Stop();

// This would throw an InvalidOperationException
MyClass myClass2 = new MyClass(mockDevice);
myClass2.Stop();

Run is starting an operation on a hardware device, and Stop is of course trying to stop that operation (sending a reset-command and starting a timeout-timer).

Anyway I would like to test various post-conditions of calling Stop, but I would like NOT to have to call Run, because I am testing Stop - not Run! I would like something like this:

MyClass myClass = new MyClass(mockDevice);
myClass.Stop();
Assert.IsTrue(mockDevice.ResetCalled);

So far I only see one possible solution, and that is to create a TestableMyClass that inherits from MyClass, that makes it possible to set the right internal state of the MyClass instance before calling Stop. The problem with this solution is that I have to change my MyClass-implementation to have protected members instead of private members, and I don't like the idea of having to change the implementation in order to test it!

Should I use this solution, is there an error in my design, or is there a smarter way of doing this?

like image 819
toxvaerd Avatar asked Mar 09 '09 08:03

toxvaerd


People also ask

Can unit tests depend on each other?

Unit tests should not affect each other. Unit tests should be deterministic. Unit tests should not depend on any external state.

Which method is used for unit testing?

Unit tests can be performed manually or automated. Those employing a manual method may have an instinctual document made detailing each step in the process; however, automated testing is the more common method to unit tests. Automated approaches commonly use a testing framework to develop test cases.

What is unit testing using dependency injection?

Dependency injection allows unit testing, but it also allow modification of an object's behavior without altering the code of that object (open/closed principle). So, it isn't just testable code, but flexible code that results.

What are the two types of unit testing?

There are 2 types of Unit Testing: Manual, and Automated.


2 Answers

As far as I see it, you are already testing Stop in the two ways in which it can be used (with and without a running operation). As long as the mockDevice is doing its job, it seem to me that you're testing it reasonably. Ideally you should be able to verify the commands sent to the device etc (which most mock frameworks will make simple).

like image 160
Marc Gravell Avatar answered Oct 14 '22 00:10

Marc Gravell


In this situation, personally, I would have two tests for this:

  1. Test without Run() being called first. I would test if it really throws the exception. I would also test if the post conditions are what I expect them to be.
  2. Test with Run() being called first. I would test only the post conditions, that I expect.

Those are the only two important uses of the method that have different behaviors - therefor I would test them both.

EDIT: I understand, why you don't want to call run, before stop - you think that if run fails, the test, that is supposed to only test stop method will most likely fail as well.

However, I would assume, that you also have test for the run method. This means, that when the tests, that test the behavior of run method pass - stop method tests must pass as well. If the run method tests fail, then the results of run method tests are undefined - they may or may not fail.

So, I'd say, don't be afraid to call other dependent methods in your tests, but make sure you test those dependent methods in separate tests.

like image 29
Paulius Avatar answered Oct 13 '22 23:10

Paulius