We have small set of environment variables exposed to control our application behavior. Application code is in java. (Environment variables may be evil, but the have a purpose in this special case)
What is the best way to unit test this? How can I create environment variables, set it to different values and call the tests repeatedly?
Current solution is to use env element in junit tasks . For example below
<env key="BASE_PLUGINS_FOLDER" value="c:/temp"/>
code sets environment variable for the test. (This works only when fork mode is set to true)
This means I have to create multiple test sections in ant build file and corresponding test else where. This could become unmanageable pretty fast.
I feel there could be a better way, that is fully a junit-java code. Not sure how.
You should encapsulate how you retrieve these variables. Not only will it allow you to change the way you pass them around (env variable, system properties, configuration file, etc...) but it will also more testable.
Then you can define two different implementations: one that actually reads the environment (which you use in production) and one where you can specify these values yourself in Java (which you use in your tests).
Here is a hack given by my friend..
Class<?> processEnvironmentClass = Class.forName("java.lang.ProcessEnvironment");
Field theEnvironmentField = processEnvironmentClass.getDeclaredField("theCaseInsensitiveEnvironment");
theEnvironmentField.setAccessible(true);
#SuppressWarnings({"unchecked"}) // this will be a Map or the test will fail if Java internals are changed
Map<String, String> env = (Map<String, String>) theEnvironmentField.get(null);
env.put(name, val);
// now System.getenv will return what we want
//noinspection CallToSystemGetenv
assertEquals("Problems setting up environment variable for test: " + name, val, System.getenv(name));
I fear this is a useless, frustrating answer... but consider redesigning the app to allow overriding the environment variables.
All access to them would need to be funneled through one place, which would also look for your choice of config mechanism -
-D,
or property file,
or property file pointed at by -D,
or runtime-created config object passed by test setup,
or smoke signals,
or ...
This can be solved using System Stubs (https://github.com/webcompere/system-stubs) in JUnit 4 and JUnit 5:
JUnit 4:
#Rule
public EnvironmentVariablesRule env = new EnvironmentVariablesRule("BASE_PLUGINS_FOLDER", "/tmp/something");
#Test
public void test() {
// variable is set here
}
Or in JUnit 5:
#ExtendWith(SystemStubsExtension.class)
class SomeTest {
#SystemStub
private EnvironmentVariables env = new EnvironmentVariables("BASE_PLUGINS_FOLDER", "/tmp/something");
#Test
void envSetHere() {
// environment variable is set
}
}
Related
I want that don't execute part of my code when I run the app for Unit testing, the problem is one my functions is save one object in BD and I want avoid this.
api.getUsers(completion:{(objects)
//In this response I save the object in BD
})
I don't think you really want to conditionally execute something at runtime based if you are running unit tests or not. That would be a terrible idea IMHO.
What you probably want in your unit tests is to create a mock object of your api class and then inject the mocked version into the class you are testing.
Does your operating system has environmental values? In React, I solve this with checking process.env.NODE_ENV !='test'
You can set an on-launch argument like isTest to YES in your scheme properties (section Test).
And, in your function use this :
BOOL isTest = [[NSUserDefaults standardUserDefaults] boolForKey:#"isTest"];
I'd like to get a certain value from an environment variable in my Kotlin app, but I can't find anything about reading environment variables in the core libraries documentation.
I'd expect it to be under kotlin.system but there's really not that much there.
It is really easy to get a environment value if it exists or a default value by using the elvis operator in kotlin:
var envVar: String = System.getenv("varname") ?: "default_value"
You could always go down this approach:
val envVar : String? = System.getenv("varname")
Though, to be fair, this doesn't feel particularly idiomatic, as you're leveraging Java's System class, not Kotlin's.
And if you want to handle env var which do exists but is empty:
val myEnv = (System.getenv("MY_ENV") ?: "").ifEmpty { "default_value" }
(see edit history for previos versions)
You can use the kotlin extension Konfig
Konfig - A Type Safe Configuration API for Kotlin
Konfig provides an extensible, type-safe API for configuration properties gathered from multiple sources — built in resources, system properties, property files, environment variables, command-line arguments, etc.
For example: Key("http.port", intType)
I want to be able, to configure Simple Injector differently for each developer (for prototyping purposes for example).
The default configuration should be hardcoded, of course.
I have used Unity before, and there I was able to overwrite the hardcoded registrations by an XML configuration file. This config file was not under source control, and so other developers could overwrite the hardcoded registrations with their custom registrations without interfering with others.
The developers should not need to submit their configuration to source control.
Is such a scenario supported by Simple Injector ?
Is there any best practice for such a scenario ?
Does this make sense at all, or is there a better way to achieve what I want?
One of the design decisions for Simple Injector is to not support XML based configuration out-of-the-box. This decision is described here but can be summarizes as:
XML based configuration is brittle, error prone and always provides a
subset of what you can achieve with code based configuration. General
consensus is to use code based configuration as much as possible and
only fall back to file based configuration for the parts of the
configuration that really need to be customizable after deployment.
These are normally just a few registrations since the majority of
changes would still require developer interaction (write unit tests or
recompile for instance). Even for those few lines that do need to be
configurable, it’s a bad idea to require the fully qualified type name
in a configuration file. A configuration switch (true/false or simple
enum) is more than enough. You can read the configured value in your
code based configuration, this allows you to keep the type names in
your code. This allows you to refactor easily, gives you compile-time
support and is much more friendly to the person having to change this
configuration file.
This however doesn't completely satisfy your requirements, since you don't want to "customizable after deployment". Instead, you want to customize per developer.
For this particular case, you shouldn't fall back on XML based configuration IMO. Just as you can exclude xml files using .gitignore, you can do the same with code based configuration files that developers can change, and that will compile with the rest of the application. Here's an example:
// Global.cs
public void Application_Start() {
var container = new Container();
// Default configuration here
container.Options.AllowOverridingRegistrations = true;
DeveloperOverrides.ApplyOverrides(container);
container.Options.AllowOverridingRegistrations = false;
DependencyResolver.Current = new SimpleInjectorDependencyResolver(container);
}
// DeveloperOverrides.cs
public static class DeveloperOverrides {
public static void ApplyOverrides(Container container) {
}
}
These two files can be checked in, where the DeveloperOverrides.ApplyOverrides method is left blank. After that you add the exclusion of the DeveloperOverrides.cs to your .gitignore file.
After this, developers can add their own overrides that are checked by the compiler, but are never checked in into source control:
// DeveloperOverrides.cs
public static class DeveloperOverrides {
public static void ApplyOverrides(Container container) {
container.Register<IMailSender, FakeMailSender>(Lifestyle.Singleton);
}
}
I have been using FeatureContext for storing information about a specific feature that can be reused in all scenarios in that feature. However I have some things like login information that I don't want to recreate for every feature. I want to use the [BeforeTestRun] attribute to store this, but does SpecFlow have some sort of Global Context feature (like log4net) to store this information so it can be reused by all features?
SpecFlow doesnt have a global context construct, however you have a few options that can help you share data between bindings/features:
Static members
You can use static field/property to set objects that can be used across all features during test execution. Keep thread safety in mind however, because if you run your tests in parallel you need to synchronize initialisation and any mutable access to this field. If you want this data to change per scenario you can set the object in the context when accessed, this way you can set a default, and allow the scenario to have its own copy.
Context injection
You can use SpecFlow Context injection to inject a object into step definitions via the constructor, this way you can initialize your type using its default constructor and the pass the type into the step def like so:
[Binding]
public class MyStepDefinition
{
private readonly MyContextData contextData;
public MyStepDefinition(MyContextData contextData)
{
this.contextData = contextData;
}
}
more info:
https://github.com/techtalk/SpecFlow/wiki/Sharing-Data-between-Bindings
I am dealing with a case where my tests pass or fail based on the order of declaration. This of-course points to not properly isolated tests. But I am stumped about how to go about finding the issue.
The thing is my junit tests derive from a class that is belongs to a testing framework built on junit and has some dependency injection container. The container gets reset for every test by the base class setup and so there are no lingering objects at least in the container since the container itself is new. So I am leaning toward the following scenario.
test1 indirectly causes some classA which sets up classA.somestaticMember to xyz value. test obj does not maintain any references to classA directly- but classA is still loaded by vm with a value xyz when test1 ends.
test2 access classA and trips up on somestaticmember having xyz value.
The problem is a) I dont know if this is indeed the case- how do I go about finding that ? I cannot seem to find a reference to a static var in the code...
b) is there a way to tell junit to dump all its loaded classes and do it afresh for every test method ?
You can declare a method with #Before, like
#Before public void init()
{
// set up stuff
}
and JUnit will run it before each test. You can use that to set up a "fixture" (a known set of fresh objects, data, etc that your tests will work with independently of each other).
There's also an #After, that you can use to do any cleanup required after each test. You don't normally need to do this, as Java will clean up any objects you used, but it could be useful for restoring outside objects (stuff you don't create and control) to a known state.
(Note, though: if you're relying on outside objects in order to do your tests, what you have isn't a unit test anymore. You can't really say whether a failure is due to your code or the outside object, and that's one of the purposes of unit tests.)