9

i got a question when i was unit testing my application. I Have a method that require a dependency but only that method need it so i thought to don't inject it by construct but initialize it with App::make() of the IoC container Class. But now how can i unit test that?

Let's say a short example for understand how you unit testing this function of example

class Example {

  public function methodToTest()
  {
       $dependency = App::make('Dependency');
       return $dependency->method('toTest');
  }

}

Test

public function test_MethodToTest() {
  $dependency =  m::mock('Dependency');
  $dependency->shouldReceive('method')->once()->with('toTest')->andReturn(true);

  $class = new Example();
  $this->assertTrue($class->methodToTest('toTest')); // does not work
}
Fabrizio Fenoglio
  • 5,767
  • 14
  • 38
  • 75

2 Answers2

20

You're almost there. Create an anonymous mock with the expectations that you need and then register that mock as the instance for Dependency and you should be good to go.

That would look something like this

public function test_MethodToTest() {
    $dependency =  m::mock();
    $dependency->shouldReceive('method')->once()->with('toTest')->andReturn(true);
    App::instance('Dependancy', $dependancy);

    $class = new Example();
    $this->assertTrue($class->methodToTest()); // should work
}
petercoles
  • 1,732
  • 13
  • 20
  • It works, but with getMock() `$dependency->getMock()` – Tihomir Mihaylov Sep 05 '14 at 18:41
  • No. If you use $dependency->getMock() directly you're only testing that the mock has been set up correctly, not that the Example class's methodToTest() is called as expected. If $class->methodToTest() didn't work for you, I recommend looking at the way your equivalent of the Example class has been setup. – petercoles Jan 04 '15 at 11:39
0

I would prefer to inject the dependency in Example classes constructor.

class Example{
    /** @var Dependency */
    private $dependency;

    public function __construct(Dependency $dependency){
        $this->dependency = $dependency;
    }

    public function methodToTest(){
        return $this->dependency->method('toTest');
    }
}

class Test{
    public function test_MethodToTest(){
        $mock = Mockery::mock(Dependency::class);
        $mock->shouldReceive('method')->once()->with('toTest')->andReturn(true);

        $class = new Example($mock);
        $this->assertTrue($class->methodToTest());
    }
}

In your controller, libraries you can then use IoC like this

$example = App::make(Example::class);
Mārtiņš Briedis
  • 17,396
  • 5
  • 54
  • 76