Yii2 and Codeception - custom test $params for Functional Tests - yii2

I want to set custom $params for Functional Tests. I cannot see where codeception allows defining custom params for tests. How can I define a custom params for testing? I was able to verify that the current params are getting loaded correctly. No way to override them for tests that I know of. I am used the advanced app template.

Related

How to detect if I am in 'console' mode

I am writing an app that runs from the browser. However, some model functions are also called from the Yii2 console. Therefore, I am getting errors when trying to access variables that are set in the GUI.
Is it possible to tell which mode I am in? Is there some environment variable automatically set, or should I just set some session variable in the console app to indicate the state?
You can use
if (Yii::$app instanceof \yii\console\Application)
for console, and
if (Yii::$app instanceof \yii\web\Application)
for web.
Correct variant
Yii::$app->request->isConsoleRequest
There is a simpler way to figure this out without going through the Yii objects
if (php_sapi_name() == "cli") {
return;
}
...and it works for all PHP scripts
...and it is lighter
By default for console:
Yii::$app->id == 'basic-console'
And for web application:
Yii::$app->id == 'basic'
Yii::$app->id stores the id of the loaded configuration params. By default for console application it is 'basic-console' and for web application it is 'basic' (defined in configuration file)
Yii2 provides a number of different classes for application's console and for those of type web. In addition to this division of the mode of operation of the classes, there are also a set of rules governing the organization of the code of the application. The first, fundamental, it is the respect of giving the MVC Model object information, to view the management interface with the user and, finally, to the controller the role of coordination among them. In your case it seems to sense that a piece of code runs in console but referring to classes that provide a Web interface. Probably because in some Model classes were introduced with functions with HTML or other code that should not be there. If you need two separate applications should precisely separate applications that use a type controls
yii\console\Controller
and another that uses controller type web
yii\web\Controller.
Obviously Model classes will be common and, thanks to separate controller, be sure to invoke View appropriate to the type of user interface in use. I Hope this could be useful.
Works for nginx and apache:
function isConsole()
{
return 'cli' == php_sapi_name() || !array_key_exists('REQUEST_URI', $_SERVER);
}
Pure PHP:
global $argv;
if (empty($argv)) {
// Browser mode
}
else {
// Cli mode
}

Guice injection leaking into other tests

I use Guice to instantiate a VocabularyAPI object for one of my unit tests unitTest1(). However, for another test (unitTest2()), I simply use mockito's #Mock annotation to mock an instance of the same class - VocabularyAPI.
I noticed that when I only run unitTest2() - mockito's mock setting for my VocabularyAPI is configured correctly. However, when I run the entire test suite (both unitTest1() and unitTest2()), both the tests are instantiated with the settings from the injector.
How can I limit the scope of the injected object to only inside the test that it is being injected? I want to be able to use the injected object in unitTest1() and mocked object for unitTest2().
Any problems in using local variables?
In unitTest1():
VocabularyAPI vocabularyAPI = // inject (I'm not familiar with Guice)
In unitTest2():
VocabularyAPI vocabularyAPI = Mockito.mock(VocabularyAPI.class);

Resolving a dependency while supplying values for downstream dependencies

I've been running into endless problems attempting to use Windsor with Web API and injecting HttpRequestMessage into downstream dependencies of a controller. Since I've tried all the matching answers on Stackoverflow, I'd like to ask the question in a different way:
In Castle Windsor, how can I resolve a component instance while supplying a value for a downstream dependency? That is, the supplied value is required by a component that is required by the component being resolved.
For context, I'm trying to inject HttpRequestMessage so that I can use it to resolve the request context (primarily to resolve an absolute URL).
Edit I'd also like to point out that I don't currently have a dependency on Web Host / System.Web and I'd rather not change that.
A proper approach is to
Create IMyDesiredRouteParameterProvider
Implement it. Get the current request inside it and get the url
Register it and inject it in the desired dependent class via constructor.
I made myself such an implementation and I can say that this way it works fine. You can make Web.Infrastructure assembly and put the implementation there. Or put both the interface and the implementation there if you are going to reference it from another web module.
using System;
using System.Web;
namespace RouteParameterProvider
{
interface IMyRouteParameterProvider
{
string GetRouteParameter();
}
public class ControllerActionMethodRouteParameterProvider : IMyRouteParameterProvider
{
public string GetRouteParameter()
{
string Parameter = HttpContext.Current.Request.RequestContext.RouteData.Values["controller"] as string;
if (string.IsNullOrEmpty(Parameter))
{
throw new InvalidOperationException();
}
return Parameter;
}
}
}
You can get every possible thing that the Request Context contains from :
HttpContext.Current.Request.RequestContext
And it will be better if you rethink your design decision :
I need HttpRequestMessage to be regstered prior to creating each
instance of SomethingController so that it will be available down at
the LinkGenerator layer.
Containers are to be initialized at runtime and then used to resolve.
I need HttpRequestMessage to be regstered prior to creating each
instance of SomethingController so that it will be available down at
the LinkGenerator layer.
It sounds like you want to register an item with the container at runtime, post-startup. In general, this is not a good practice--registration should be a discrete event that happens when the app is fired up, and the container's state should not be changed during runtime.
Dependency Injection is about resolving service components, not runtime state--state is generally passed via methods (method injection). In this case it sounds like your LinkGenerator component needs access to the ambient state of the request.
I'm not that familiar with HttpRequestMessage, but this answer seems to show that it is possible to retreive it from HttpContext.Current. You could make this a method on your LinkGenerator class, or wrap this call in a separate component that gets injected into LinkGenerator (HttpRequestMessageProvider?). The latter would be my preferred method, as it allows LinkGenerator to be more testable.
Given the lack of a clean way of doing this and Web API not providing information as to the hosted endpoint beyond per-request context objects, I ended up injecting the base url from configuration.
Is this library by Mark Seemann the answer? In the description he writes explicitly :
This approach enables the use of Dependency Injection (DI) because the
request can be injected into the services which require it.
Then gives an example :
// Inside an ApiController
var uri = this.Url.GetLink(a=> a.GetById(1337));
By which you can then pass the URL down the road in the service that you have injected in the controller.
UPDATE :
Mark Seemann wrote about the same exact problem here:
"Because HttpRequestMessage provides the context you may need to
compose dependency graphs, the best extensibility point is the
extensibility point which provides an HttpRequestMessage every time a
graph should be composed. This extensibility point is the
IHttpControllerActivator interface:..."
This way you can pass request context information to a component deep in the object graph by getting from the HttpRequestMessage and passing it to the DI container.
Just take a look at the interface of IHttpControllerActivator.
The WEB API framework gets the IHttpControllerActivator through DependencyResolver. You probably already replaced it by your CastleWindsorDependencyResolver. Now you have to implement and register your HttpControllerActivator and register it.
When the WEB API framework gets IHttpControllerActivator from DependencyResolver (your Castle Windsor DR) and calls IHttpControllerActivator.Create() it will pass you the HttpRequestMessage. You can get your info from there and pass it to the your CastleDR before you call Resolve(typeof(MyController)) which will resolve the whole object graph - that means you will have MyHttpContextInfo to inject in your XYZComponent deep in the resolution stack.
This way tou are passing the arguments in the last possible moment but it is still possible. In Castle Windsor I make such passing of arguments though CreationContext.AdditionalArguments["myArgument"];.

Angular - building a "public" function (newbie)

I'm After several days learning angularJS through converting my standart JS app to a ng one.
I was wondering about this simple scenario:
I have a global function called fb_connect(),
it can be used from any page (or any controller if you like) to make a facebook-based login.
This function makes a simple http call and receives a JSON object contain data to move on (display a pop up, login, etc...)
I read that I can define a Factory or a Service for my app and use it in any controller, which works fine.
So, I created a fb_connect factory function.
The problem is that now, in every page (every controller), I have to define that fb_connect in the constructor of every controller - for example :
function welcome($scope,fb_connect){});
What is the proper way to do this kind of actions using Angular without having to define these functions each and every time in every controller?
Thanks
Setting up factories and services is all part of the dependency injection system of Angular. Using that system is great when you need to create things that depend on other injected things. It's a big tree of dependencies. It's also nice for creating singletons, such that everywhere in your code end up using the same instance of some object.
It sounds to me like neither of these benefits apply in your case. I'd suggest just not using Angular's DI for it. You have some function defined globally, just call it directly and skip the DI. There's nothing wrong with that.
Of course you say it makes an Ajax call, so doesn't depend on the Angular $http service?
Your two options are:
Declare the function on the $rootScope
Inject it as a service
My advice is to go with making it a service. The whole purpose of services is explained in the Angular.js docs, just like this quote:
Angular services are singletons that carry out specific tasks common to web apps... To use an Angular service, you identify it as a dependency for the dependent (a controller, or another service) that depends on the service.
As you mentioned in your question, you'd prefer to not define the service in every controller you wish to use it in. With $rootScope you'll be injecting that also in every controller. So really it's a question of which you prefer, although to answer your question, the proper way of using a factory or service is to inject it into the controller you wish to use it in.
You can always put it in the $rootScope
myApp.run(function($rootScope, fb_connect){
$rootScope.welcome = function(){
};
});

What is the best way to pass configurations to OSGI components?

I have a set of parameters that should be configured by the user. But they are just too much to send them through RESTful services or something similar. Besides there may be another set of configurations of same parameters.
Assume that my configurations are: p1, p2, p3, ... p10
I want to make possible having more than set of initialization of these configurations such as:
(p1=x, p2=y, ... p10=1)
(p1=a, p2=b, ... p10=10)
To do that I currently implement my OSGI component with metatype=true and configurationFactory = true options so that each instance of my component will have a set of configurations initialized. Then, I process the instances in a manager component.
So the question what do you suggest for passing configurations to OSGI components from user?
Thanks
If this is really about configurations you should use the OSGi ConfigurationAdmin service. A console like the Apache Felix WebConsole can then be used to edit configurations.
If the values (or some values) can be different for each RESTful call to your application and they don't fit in a URL, you can make a POST request instead of a GET, and pass the values in the body of the request, in a suitable format.