I am using CakePHP 2.x and I want to write unit tests.
In the controller there are several places where exists a read from the Configuration file, like:
$dInterval = Configure::read('myapp.dinterval');
Is there a way to mock that value for the test?
No, such a hard coded static call cannot be mocked, at least not in the context of how the application, the framework, and PHP in general work. Technically it's possible to create mocks for static calls using an aliased class, but that would require to set up the alias outside of the test environment, as it needs to happen before the original class is being loaded.
What you can do however is simply write to the config before testing the action, eg
Configure::write('myapp.dinterval', 123);
$result = $this->testAction(/* ... */);
The original configuration is backed up before each test, and it is being restored after each test.
Related
What would be the proper thing to do for each case?
1: Context: Testing a function that creates a database as well as generating metadata for that database
Question: Normally unit test cases are supposed to be independent, but if we want to make sure the function raises an exception when trying to make a duplicate database, would it be acceptable to have ordered test cases where the first one tests if the function works, and the second one tests if it fails when calling it again?
2: Most of the other functions require a database and metadata. Would it be better to call the previous functions in the set up of each test suite to create the database and metadata, or would it be better to hard code the required information in the database?
Your automated test should model the following:
Setup
Exercise (SUT)
Verify
Teardown
In addition, each test should be as concise as possible and only expose the details that are being tested. All other infrastructure that is required to execute the test should be abstracted away so that the test method serves as documention that only exposes the inputs that are being tested in regards to what you want to verify for that particular test.
Each test should strive to start from a clean slate so that the test can be repeated with the same results each time regardless of the results of prior tests that have been executed.
I typically execute a test-setup and a test-cleanup method for each integration test or any test that depends on singletons that maintain state for the System-Under-Test and need to have it's state wiped.
Normally unit test cases are supposed to be independent, but if we want to make sure the function raises an exception when trying to make a duplicate database, would it be acceptable to have ordered test cases where the first one tests if the function works, and the second one tests if it fails when calling it again?
No, ordered tests are bad. There's nothing stopping you from having a test call another method that happens to be a test though:
#Test
public void createDataBase(){
...
}
#Test
public void creatingDuplicateDatabaseShouldFail(){
createDataBase();
try{
//call create again should fail
//could also use ExpectedException Rule here
createDataBase();
fail(...);
}catch(...){
...
}
}
Most of the other functions require a database and metadata. Would it be better to call the previous functions in the set up of each test suite to create the database and metadata, or would it be better to hard code the required information in the database?
If you use a database testing framework like DbUnit or something similar, it can reuse the same db setup over and over again in each test.
I'm writing a variety of Model Tests in CakePHP (PHPUnit)
In TravisCI, I get something like: "Base table or view not found: 1146 Table 'test.events'
In Cake's test runner I get an assertion failure.
The problem I am having is there are methods in my ModelClasses that I am trying to test which call other models with App::uses. For example:
Method on User model:
public function getOtherData() {
App::uses('Event', 'Model');
$this->Event = new Event;
return $this->Event->find('all');
}
And the test:
public function testGetOtherData() {
$result = $this->User->getOtherData();
$this->assertTrue(!empty($result));
}
Note the above example is just that. An example, simplified to show the problem. I understand that the above example has better 'cake' ways of doing it.
Also, I am using defining required fixtures and they work just fine. (I know this by another method in the model which uses a join in the find, instead of App::Uses())
EDIT:
The code when run works, BUT the UnitTest is looking for the other models data (When using App::uses) in the default database, and not the test database. Why doesn't it use the test database? Am I missing something?
LAST NOTE
Using App::uses() and then instantiating the class will work at runtime. But during testing it will fail, as it attempts to use the default database connection, instead of the test database connection.
Per the selected answer, rather than using App::uses, Cakes built in class registry, ClassRegistry::init('Model', true);, you can include a Model from inside another model method.
It's not generally a good idea to instantiate an object in the middle of your functions using the new statement. This is why -- there's no way to block or redirect that call. Also, it's not necessarily easy to get the right parameters to the object's constructor when it's in the middle of another function, so it's best to keep that code separate.
The right way to do this is to use a different method call to get your object. If you use Cake's ClassRegistry::init() to create model objects, they should use the test database.
If you need to create other non-Cake objects, it's best to create them using some other function, e.g. $this->fetchMeOneOThemEventThingies(). Then, during testing, you can mock out that function and have it return something else. Or, you could use some other DI container like pimple, which will take the same role as Cake's ClassRegistry.
If you need a mock model object for testing, be sure to pass the appropriate arguments to the model's constructor as the third parameter to getMock(), or it may use the production database.
I am a bit confused
from wiki:
"This means that a true mock... performing tests on the data passed into the method calls as arguments."
I never used unit testing or mock framework. I thought unit tests are for automated tests so what are mock tests for?
What I want is a object replacing my database I might use later but still dont know what database or orm tool I use.
When I do my programm with mocks could I easily replace them with POCO`s later to make entity framework for example working pretty fast?
edit: I do not want to use unit testing but using Mocks as a full replacement for entities + database would be nice.
Yes, I think you are a bit confused.
Mock frameworks are for creating "Mock" objects which basically fake part of the functionality of your real objects so you can pass them to methods during tests, without having to go to the trouble of creating the real object for testing.
Lets run through a quick example
Say you have a 'Save()' method that takes a 'Doc' object, and returns a 'boolean' success flag
public bool Save(Doc docToSave(){...}
Now if you want to write a unit test for this method, you are going to have to first create a document object, and populate it with appropriate data before you can test the 'Save()' method. This requires more work than you really want to do.
Instead, it is possible to use a Mocking framework to create a mock 'Doc' object for you.
Syntax various between frameworks, but in pseudo-code you would write something like this:
CreateMock of type Doc
SetReturnValue for method Doc.data = "some test data"
The mocking framework will create a dummy mock object of type Doc that correctly returns "some test data" when it's '.data' property is called.
You can then use this dummy object to test your save method:
public void MyTest()
{
...
bool isSuccess = someClass.Save(dummyDoc);
...
}
The mocking framework ensures that when your 'Save()' method accesses the properties on the dummyDoc object, the correct data is returned, and the save can happen naturally.
This is a slightly contrived example, and in such a simple case it would probably be just as easy to create a real Doc object, but often in a complex bit software it might be much harder to create the object because it has dependencies on other things, or it has requirements for other things to be created first. Mocking removes some of that extra overload and allows you to test just the specific method that you are trying to test and not worry about the intricacies of the Doc class as well.
Mock tests are simply unit tests using mocked objects as opposed to real ones. Mocked objects are not really used as part of actual production code.
If you want something that will take the place of your database classes so you can change your mind later, you need to write interfaces or abstract classes to provide the methods you require to match your save/load semantics, then you can fill out several full implementations depending on what storage types you choose.
I think what you're looking for is the Repository Pattern. That link is for NHibernate, but the general pattern should work for Entity Framework as well. Searching for that, I found Implementing Repository Pattern With Entity Framework.
This abstracts the details of the actual O/RM behind an interface (or set of interfaces).
(I'm no expert on repositories, so please post better explanations/links if anyone has them.)
You could then use a mocking (isolation) framework or hand-code fakes/stubs during initial development prior to deciding on an O/RM.
Unit testing is where you'll realize the full benefits. You can then test classes that depend on repository interfaces by supplying mock or stub repositories. You won't need to set up an actual database for these tests, and they will execute very quickly. Tests pay for themselves over and over, and the quality of your code will increase.
I use Composite WPF(Prism) and I am trying to unit test that my Controller does in fact subscribe to a Composite Event.
My subscription code looks as follows...
//Init Events.
this.eventAggregator.GetEvent<PlantTreeNodeSelectedEvent>().Subscribe(
ShowNodeDetails, ThreadOption.UIThread);
My unit testing code looks as follows (I use Moq as my Mocking Framework and Unity as my DI Framework)...
Mock<PlantTreeNodeSelectedEvent> eventBeingListenedTo = new Mock<PlantTreeNodeSelectedEvent>();
eventAggregatorMock.Setup(e => e.GetEvent<PlantTreeNodeSelectedEvent>()).Returns(eventBeingListenedTo.Object);
//Initialize the controller to be tested.
IPlantTreeController controllerToTest = container.Resolve<IPlantTreeController>();
//Verify.
eventBeingListenedTo.Verify(
e => e.Subscribe(It.IsAny<Action<string>>(), ThreadOption.UIThread));
This subscribe method IS being called (I've verified by running with the debugger), but the Verify always fails with "Invocation was not performed on the mock: e => e.Subscribe..."
Any idea what I am doing wrong?
In your code, it seems like the eventAggregatorMock instance is never used. I would guess that you need to register it with the container so that it is being used by controllerToTest.
You seem to be testing too much in your unit test. You shouldn't need a container, you should just create your controller providing mock dependencies, because you should only test 1 thing in a unit test (you don't need to test that the DI framework works, as it usually does ;-)). It will also ensure that you provide the correct mocks, now it is not clear from your code as Mark Seemann has pointed out in his answer.
You may try to setup a method call under question in the beginning. Sometimes it seems to help moq to verify the class appropriately. In this case you may also want to setup your mock behavior to be Strict in the constructor, so that you will get the test failed for other, unexpected calls to your mock.
eventBeingListenedTo.Setup(e => e.Subscribe(It.IsAny<Action<string>>(), ThreadOption.UIThread));
use a mocking aggregator like this (for Rhino.Mocks)
http://adammills.wordpress.com/2010/12/13/auto-mocking-eventaggregator/
If you use ThreadOption.UIThread, it calls Dispatcher.Invoke which won't work without a Message Loop; which isn't normally running in unit tests.
I've got many objects with methods that require database access. We're looking to get into unit testing but are keen to avoid the use of mock objects if possible. I'm wondering if there is a way to refactor the Validate method shown below so that it wouldn't need db access. In the actual application there is usually a fair bit more going on but I think this simplified example should be enough.
We'll learn to use mock objects if we need to but it just seems like a lot of overhead, so I'm looking for alternatives.
public class Person
{
public string Name;
public string Validate()
{
if (PersonDA.NameExists(Name))
{
return "Name Already Used";
}
}
}
Personally I'd just go the mock object route. It's much more flexible and it sounds like you're wanting to go the route of putting test code in your actual object?
Regarless, extract the validation code into a PersonValidator object with a method for boolean isValid(Person). Then in the test code use a mock validator which just returns true or false based on the test case.
The Person class is hard to unit-test because it has a hidden, static dependency on database access code. You can break this coupling by introducing a dynamic collaboration between the Person and some new type of object that provides it with the information it needs to validate its state. In your unit tests of the Person you can test what happens when it is valid or invalid without hitting the database by passing the Person object "stub" implementations of it's collaborator.
You can test the real implementation, which hits the database, in a separate set of tests. Those tests will be slower but there should be fewer of them because they will be direct translations of accessor methods to database queries with no complex logic of their own.
You can call that "using mock objects" if you like but, because your current design means you only need to stub queries, not expect commands, a mock object framework is a too complicated tool for the job. Hand-written stubs will make test failures easier to diagnose.
Take a look at dbunit, it's especially set up to populate a small test database so you can use your real objects on a mock database during unit testing. Testing with it is far easier than developing mock objects, far safer than modifying your data access code, and far more thorough than either.
Why are you trying to avoid mocks exactly? If you are going to practice unit testing and you have data access code, its going to be easiest to get comfortable with the mock/stub/inject way of doing things.
If it's because you dont want to bring in a mocking framework you could code up some simple stubs as you need them.
Putting your data access code behind an interface will let to avoid the need for a database. Consider using dependency injection to insert the mock or stub data access code during your tests.
You should just set up a database that is used for the unit testing.
If you use mockups for all the data access, you wouldn't actually be testing much? :)