Mockery not executing mock method - unit-testing

I have class Name Validator and it has a method forVote.
This is my code.
public function test_should_set_default()
{
$this->mock = \Mockery::mock(Validator::class);
$this->mock->shouldReceive('forVote')
->andReturnTrue();
$this->app->instance(Validator::class,$this->mock);
$factory = new Factory();
$this->assertTrue($factory->setDefault());
}
So Factory calls Processor which calls Validator. Now I want mock validator to run. But it calls the real method.
What am I doing wrong?

https://laravel.com/docs/5.6/container#introduction
since the repository is injected, we are able to easily swap it out
with another implementation. We are also able to easily "mock", or
create a dummy implementation of the UserRepository when testing our
application.
My guess is you are perhaps currently instantiating your dependencies like so:
$processor = new Processor() and $validator = Validator::make(...);
So, in order to have your mocked class be used, you should use Dependency injection which just means your classes should inject your dependencies via the __construct method.
Your Factory class should be like:
class Factory {
$processor;
public function __construct(Processor $processor)
{
$this->processor = $processor;
}
public function setDefault()
{
$this->processor->callingValidator();
}
}
and your Processor to be like:
class Processor {
$validator;
/**
* The Validator will resolve to your mocked class.
*
*/
public function __construct(Validator $validator)
{
$this->validator = $validator;
}
public function callingValidator()
{
$this->validator->make();
}
}

Related

gmock Multiple mock instances, but only one is effective

I would like to test a class (Controller) that manages a set of entities of a certain kind. Entities are created internally in this class because a factory would be an overkill here, so here is how I inject mocks into it:
class TestController : public Controller {
public:
/* Mechanism for a mock injection */
std::shared_ptr<IEntity> create_entity() override {
return temp_entity;
}
/* Variable to hold the entity being injected */
std::shared_ptr<IEntity> temp_entity;
};
Production code invokes create_entity() in the Controller class, which I overload here, and adds the result to a container. temp_entity is the way I supply my mocks and the test, where I supply two distinct mock instances, looks like this:
class MockEntity : public IEntity {
MOCK_METHOD0(perform_operation, bool());
}
TEST(ControllerTest, TestFailure) {
std::shared_ptr<TestController> controller = std::make_shared<TestController>();
std::shared_ptr<MockEntity> entity1 = std::make_shared<MockEntity>();
controller->temp_entity = entity1;
controller->add_entity(); // This invokation fetches the result of create_entity()
std::shared_ptr<MockEntity> entity2 = std::make_shared<MockEntity>();
controller->temp_entity = entity2;
controller->add_entity(); // This invokation fetches the result of create_entity()
EXPECT_CALL(*entity1, perform_operation().WillOnce(::testing::Return(true));
EXPECT_CALL(*entity2, perform_operation().WillOnce(::testing::Return(false));
controller->run();
}
controller.run() only concurrently executes perform_operation() on each of the entities.
When the test is run, the function in the second expectation is called twice and the function in the first expectation is not run at all. I am sure that the controller operates on two distinct versions of an entity before executing run() function.
Is there a fundamental problem in what I am trying to do? How can I separate my expectations for these two mocks in a test? I tried creating two distinct mock classes with perform_operation() method being implemented in the mock body and when running the test in the debugger I still hit the method of one mock class twice.
The test looks correct and the way, how you inject the mocks into the system under test, is an absolutely reasonable method.
I suppose, the critical issue is in your class under Test. I rebuild your Test with the following controller:
class Controller {
public:
virtual std::shared_ptr<IEntity> create_entity() = 0;
void add_entity() {
auto entity = create_entity();
entities.push_back(entity);
}
void run() {
for(auto e : entities) {
bool i = e->perform_operation();
}
}
std::vector<std::shared_ptr<IEntity> > entities;
};
With this class the test succeeded like expected.

Unit testing a started Service which has a few fields injected into it?

I am a Dagger newbie.
TL;DR:
If an Android Service has any fields injected into it using Dagger, then in order to actually perform the injection, I need to have an instance of that Service.
In Robolectric tests, this corresponds to MyService service = Robolectric.buildService(MyService.class).get(). And then, objectGraph.inject(service);
However, rest of the code that actually starts MyService still uses context.startService(context, MyService.class);.
Question: What is the idiomatic way in Dagger to address this mismatch?
Let's say I have a Service as follows:
public class MyService {
#Inject Parser parser;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
String data = intent.getStringExtra("data_to_be_parsed");
parser.parse(data);
}
}
Elsewhere in my code, I have an ApiClient class that does this:
public class ApiClient{
public static void parseInBackground(Context context, String data){
//This service does not have its fields injected
context.startService(new Intent(context, MyService.class).putExtra("data_to_be_parsed", data));
}
}
That parseInBackground method will be called from an Activity in response to user interaction.
Now, I'm following TDD and hence, I haven't yet written the Application Module for this. Here's the test module:
#Module(injects = MyService.class)
public class TestModule {
#Provides #Singleton Parser provideParser(){
return new MockParser();
}
}
And finally, the test case:
#RunWith(Robolectric.class)
public class ApiTest {
#Test
public void parseInBackground_ParsesCorrectly(){
//This service has its fields injected
MyService service = Robolectric.buildService(MyService.class).get();
ObjectGraph.create(new TestModule()).inject(service);
ApiClient.parseInBackground(Robolectric.application, "<user><name>droid</name></user>");
//Asserts here
}
}
As you can see, in the test, I retrieve an instance of the service and then inject the MockParser into it. However, the ApiClient class directly starts the service using an Intent. I don't have a chance to perform the injection.
I am aware that I can have MyService perform an injection on itself:
public void onCreate(){
ObjectGraph.create(new TestModule()).inject(this);
}
But then, I am hardcoding the TestModule here.
Is there an existing idiom in Dagger to set up dependencies for such situations?
It's the wrong way to hardcode your modules either in tests or in services. Better approach is to perform creation via your custom Application object which in turn will hold singleton ObjectGraph object. For example:
// in MyService class
#Override public void onCreate() {
super.onCreate();
MyApp.from(context).inject(this);
}
// in MyApp class
public static MyApp from(Context context) {
return (MyApp) context.getApplicationContext();
}
//...
private ObjectGraph objectGraph;
#Override public void onCreate() {
// Perform Injection
objectGraph = ObjectGraph.create(getModules());
objectGraph.inject(this);
}
public void inject(Object object) {
objectGraph.inject(object);
}
protected Object[] getModules() {
// return concrete modules based on build type or any other conditions.
}
Alternatively, you can refactor last method out into separate class and make different implementations for different flavors or build types. Also you may want to set overrides=true in your TestModule's annotation.

Laravel mockery

I am trying to set up the simplest of tests in my controller but, as with most things Laravel, there are no decent tutorials to demonstrate the simple stuff.
I can run a simple test (in a file called UserControllerTest) like this:
public function testIndex()
{
$this->call('GET', 'users');
$this->assertViewHas('users');
}
This calls the /users route and passes in an array users.
I want to do the same with Mockery but how?
If I try this:
public function testIndex()
{
$this->mock->shouldReceive('users')->once();
$this->call('GET', 'users');
}
I get an error that "Static method Mockery_0_users::all does not exist on this mock object.
Why not? I am mocking User which extends Ardent and in turn extends Eloquent. Why does ::all not exist for the mock?
BTW, these are the set-up functions for Mockery:
public function setUp()
{
parent::setUp();
$this->mock = $this->mock('User');
}
public function mock($class)
{
$mock = Mockery::mock($class);
$this->app->instance($class, $mock);
return $mock;
}
You can't directly mock an Eloquent class. Eloquent is not a Facade and your User model neither. There is a bit of magic in Laravel but you can't do things like that.
If you want to mock your User class, you have to inject it in the controller constructor. The repository pattern is a good approach if you want to do that. There is a lot of articles about this pattern and Laravel on Google.
Here some pieces of code to show you how it could look like :
class UserController extends BaseController {
public function __construct(UserRepositoryInterface $users)
{
$this->users = $users;
}
public function index()
{
$users = $this->users->all();
return View::make('user.index', compact('users'));
}
}
class UserControllerTest extends TestCase
{
public function testIndex()
{
$repository = m::mock('UserRepositoryInterface');
$repository->shouldReceive('all')->andReturn(new Collection(array(new User, new User)));
App::instance('UserRepositoryInterface', $repository);
$this->call('GET', 'users');
}
}
If it seems to be too much structuration for your project you can just call a real database in your tests and don't mock your model classes... In a classic project, it just works fine.
This function is part of a project called apiato.io you can use it to mock any class in Laravel, even facade, basically anything that can be resolved with the IoC, which is almost all classes if you are using proper dependency injection:
/**
* Mocking helper
*
* #param $class
*
* #return \Mockery\MockInterface
*/
public function mock($class)
{
$mock = Mockery::mock($class);
App::instance($class, $mock);
return $mock;
}

How to mock App::make() on UnitTesting Laravel 4

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
}
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
}
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);

moq callbase for methods that do not return value (void methods)

I am trying to mock my class that is under test, so that I can callbase on individual methods when testing them. This will allow me to test the method setup as callbase only, and all other methods (of the same class) called from within the test method will be mocked.
However, I am unable to do this for the methods that do not return a value. The intellisense just doesn't display the option of callbase, for methods that do not return value.
Is this possible?
The Service Class:
public class Service
{
public Service()
{
}
public virtual void StartProcess()
{
//do some work
string ref = GetReference(id);
//do more work
SendReport();
}
public virtual string GetReference(int id)
{
//...
}
public virtual void SendReport()
{
//...
}
}
Test Class setup:
var fakeService = new Mock<Service>();
fakeService.Setup(x => x.StartProcess());
fakeService.Setup(x => x.GetReference(It.IsAny<int>())).Returns(string.Empty);
fakeService.Setup(x => SendReport());
fakeService.CallBase = true;
Now in my test method for testing GetReference I can do this:
fakeService.Setup(x => x.GetReference(It.IsAny<int>())).CallBase();
but when i want to do the same for StartProcess, .CallBase is just not there:
fakeService.Setup(x => x.StartProcess()).CallBase();
it becomes available as soon as i make the method to return some thing, such a boolean value.
First of all, your mock will not work because methods on Service class are not virtual. When this is a case, Moq cannot intercept calls to insert its own mocking logic (for details have a look here).
Setting mock.CallBase = true instructs Moq to delegate any call not matched by explicit Setup call to its base implementation. Remove the fakeService.Setup(x => x.StartProcess()); call so that Moq can call base implementation.