I have considerable success unit testing my Pic code by abstracting out the hardware access and mocking it in my tests.
For example I abstract PORTA with
#define SetPortA(v) {PORTA = v;}
then SetPortA can easily be mocked, without adding overhead code in the Pic version.
Once the hardware abstraction has been tested a while I soon find that generally code goes from the test rig to the Pic and works first time.
Update:
I use a #include seam for the unit code, #including the unit code in a c++ file for the test rig, and a c file for the target code.
As an example I want to multiplex four 7 segment displays, one port driving the segments and a second selecting the display. The display code interfaces with the displays via SetSegmentData(char) and SetDisplay(char). I can mock these in my c++ test rig and check that I get the data I expect. For the target I use #define so that I get a direct assignment without the overhead of a function call
#define SetSegmentData(x) {PORTA = x;}